From ffb3e99f4ebdb8b3c260c3ce647a0ebc2a3bb706 Mon Sep 17 00:00:00 2001 From: payton Date: Mon, 17 Apr 2023 15:22:31 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=9B=B4=E6=96=B00417IQ=EF=BC=9B2.=E8=B0=83?= =?UTF-8?q?=E6=95=B4sf=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .vscode/settings.json | 11 + S530_VS.sln | 31 + S530_VS.vcxproj | 84203 +++++ S530_VS.vcxproj.filters | 252301 +++++++++++++++ S530_VS.vcxproj.user | 4 + build/.nvt_modelcfg | 2 +- code/application/source/cardv/OutputImg.mk | 4 +- .../source/cardv/SrcCode/Startup/sifar_app.c | 1 + .../SrcCode/UIApp/MovieStamp/MovieStamp.c | 10 +- .../SrcCode/UIApp/Photo/UIAppPhoto_Exe.c | 15 +- .../UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h | 2 +- .../UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c | 27 + .../UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h | 10 +- code/application/source/sf_app/MakeConfig.mk | 5 + code/application/source/sf_app/Makefile | 184 +- .../source/sf_app/build/cardv_inc.mk | 3 + .../application/source/sf_app/build/config.mk | 14 + code/application/source/sf_app/build/inc.mk | 72 + .../source/sf_app/build/modbuild.mk | 75 + .../source/sf_app/code/include/HMACSHA.h | 19 + .../source/sf_app/code/include/aos_util.h | 41 + .../source/sf_app/code/include/apr.h | 644 + .../source/sf_app/code/include/apr_errno.h | 1316 + .../source/sf_app/code/include/apr_general.h | 243 + .../source/sf_app/code/include/apr_lib.h | 243 + .../source/sf_app/code/include/apr_pools.h | 817 + .../source/sf_app/code/include/apr_sha1.h | 122 + .../source/sf_app/code/include/apr_strings.h | 390 + .../source/sf_app/code/include/apr_want.h | 126 + .../source/sf_app/code/include/apr_xlate.h | 164 + .../source/sf_app/code/include/apu.h | 146 + .../source/sf_app/code/include/apu_config.h | 52 + .../source/sf_app/code/include/bitstream.h | 48 + .../source/sf_app/code/include/cJSON.h | 276 + .../source/sf_app/code/include/mask.h | 47 + .../source/sf_app/code/include/mbedtls.h | 25941 ++ .../source/sf_app/code/include/mmask.h | 44 + .../source/sf_app/code/include/mqrspec.h | 167 + .../source/sf_app/code/include/qrenc.h | 44 + .../source/sf_app/code/include/qrencode.h | 415 + .../sf_app/code/include/qrencode_inner.h | 97 + .../source/sf_app/code/include/qrinput.h | 132 + .../source/sf_app/code/include/qrspec.h | 190 + .../source/sf_app/code/include/rscode.h | 51 + .../source/sf_app/code/include/sf_aes.h | 34 + .../source/sf_app}/code/include/sf_base64.h | 0 .../source/sf_app/code/include/sf_bmp.h | 47 + .../source/sf_app/code/include/sf_commMng.h | 39 + .../source/sf_app/code/include/sf_commu_mcu.h | 69 + .../sf_app/code/include/sf_commu_mcu_reg.h | 349 + .../source/sf_app/code/include/sf_dataMng.h | 90 + .../source/sf_app/code/include/sf_datahttp.h | 56 + .../source/sf_app/code/include/sf_debug.h | 68 + .../source/sf_app/code/include/sf_dev_other.h | 24 + .../source/sf_app/code/include/sf_dev_usb.h | 35 + .../source/sf_app/code/include/sf_device.h | 64 + .../source/sf_app/code/include/sf_eg91_gps.h | 75 + .../sf_app/code/include/sf_eg91_server.h | 150 + .../source/sf_app/code/include/sf_eg91_sim.h | 118 + .../source/sf_app/code/include/sf_fileMng.h | 61 + .../source/sf_app/code/include/sf_hal_gpio.h | 30 + .../sf_app/code/include/sf_hal_ttyusb.h | 89 + .../sf_app/code/include/sf_http_server.h | 52 + .../source/sf_app/code/include/sf_keymng.h | 72 + .../source/sf_app/code/include/sf_ledmng.h | 94 + .../source/sf_app/code/include/sf_log.h | 113 + .../sf_app/code/include/sf_message_queue.h | 29 + .../source/sf_app/code/include/sf_module.h | 130 + .../sf_app/code/include/sf_opera_adapt.h | 39 + .../sf_app/code/include/sf_param_common.h | 67 + .../sf_app/code/include/sf_param_enum.h | 434 + .../sf_app/code/include/sf_param_struct.h | 359 + .../source/sf_app/code/include/sf_qrcode.h | 40 + .../source/sf_app/code/include/sf_qrutils.h | 46 + .../source/sf_app/code/include/sf_storeMng.h | 80 + .../source/sf_app/code/include/sf_systemMng.h | 83 + .../sf_app/code/include/sf_transdata1.h | 53 + .../source/sf_app/code/include/sf_type.h | 54 + .../source/sf_app/code/include/sha256.h | 33 + .../source/sf_app/code/include/split.h | 57 + .../sf_app/code/source/4gMng/sf_eg91_gps.c | 1027 + .../sf_app/code/source/4gMng/sf_eg91_server.c | 1451 + .../sf_app/code/source/4gMng/sf_eg91_sim.c | 2143 + .../sf_app/code/source/4gMng/sf_http_server.c | 466 + .../sf_app/code/source/4gMng/sf_module.c | 305 + .../sf_app/code/source/4gMng/sf_opera_adapt.c | 1703 + .../source/sf_app/code/source/app/sf_app.c | 75 +- .../source/sf_app/code/source/app/sf_app.o | Bin 900 -> 0 bytes .../source/sf_app/code/source/app/sf_device.c | 503 + .../source/sf_app/code/source/app/sf_test.c | 23 - .../source/sf_app/code/source/app/sf_test.o | Bin 892 -> 0 bytes .../code/source/commMng/sf_message_queue.c | 113 + .../sf_app/code/source/commMng/sf_share_mem.c | 218 + .../sf_app/code/source/dataMng/sf_dataMng.c | 352 + .../sf_app/code/source/dataMng/sf_datahttp.c | 1403 + .../code/source/dataMng/sf_transdata1.c | 1722 + .../sf_app/code/source/debugMng/sf_debug.c | 140 + .../sf_app/code/source/devMng/sf_dev_other.c | 47 + .../sf_app/code/source/devMng/sf_dev_usb.c | 45 + .../sf_app/code/source/devMng/sf_keymng.c | 231 + .../sf_app/code/source/devMng/sf_ledmng.c | 242 + .../source/sf_app/code/source/fileMng/cJSON.c | 2953 + .../sf_app/code/source/fileMng/sf_fileMng.c | 664 + .../sf_app/code/source/gpio/sf_hal_gpio.c | 155 + .../source/sf_app/code/source/logMng/sf_log.c | 273 + .../code/source/paramMng/sf_param_common.c | 657 + .../sf_app/code/source/qrcodeMng/bitstream.c | 250 + .../sf_app/code/source/qrcodeMng/mask.c | 366 + .../sf_app/code/source/qrcodeMng/mmask.c | 191 + .../sf_app/code/source/qrcodeMng/mqrspec.c | 292 + .../sf_app/code/source/qrcodeMng/qrenc.c | 358 + .../sf_app/code/source/qrcodeMng/qrencode.c | 684 + .../sf_app/code/source/qrcodeMng/qrinput.c | 1438 + .../sf_app/code/source/qrcodeMng/qrspec.c | 573 + .../sf_app/code/source/qrcodeMng/rscode.c | 340 + .../sf_app/code/source/qrcodeMng}/sf_base64.c | 0 .../sf_app/code/source/qrcodeMng/sf_bmp.c | 298 + .../sf_app/code/source/qrcodeMng/sf_qrcode.c | 116 + .../sf_app/code/source/qrcodeMng/split.c | 324 + .../sf_app/code/source/signatureMng/HMACSHA.c | 285 + .../code/source/signatureMng/aos_util.c | 145 + .../code/source/signatureMng/apr_sha1.c | 376 + .../sf_app/code/source/signatureMng/sha256.c | 331 + .../sf_app/code/source/storeMng/sf_storeMng.c | 390 + .../code/source/systemMng/sf_commu_mcu.c | 1028 + .../code/source/systemMng/sf_commu_mcu_reg.c | 900 + .../code/source/systemMng/sf_systemMng.c | 478 + .../sf_app/code/source/ttyusb/sf_hal_ttyusb.c | 415 + .../source/sf_app/code/source/utils/mbedtls.c | 66851 ++++ .../source/sf_app/code/source/utils/sf_aes.c | 169 + .../sf_app/code/source/utils/sf_qrutils.c | 236 + .../sf_app/code/source/utils/sf_qrutils.o | Bin 0 -> 3348 bytes .../source/sf_app/component/Makefile | 20 + .../source/sf_app/component/liveMng/Makefile | 11 + .../liveMng/inc/exports/aiot_authorize_api.h | 135 + .../liveMng/inc/exports/iot_export_awss.h | 188 + .../liveMng/inc/exports/iot_export_coap.h | 207 + .../liveMng/inc/exports/iot_export_compat.h | 33 + .../inc/exports/iot_export_diagnosis.h | 950 + .../liveMng/inc/exports/iot_export_errno.h | 250 + .../liveMng/inc/exports/iot_export_event.h | 64 + .../liveMng/inc/exports/iot_export_guider.h | 33 + .../liveMng/inc/exports/iot_export_http.h | 130 + .../liveMng/inc/exports/iot_export_http2.h | 127 + .../inc/exports/iot_export_http2_stream.h | 113 + .../liveMng/inc/exports/iot_export_linkkit.h | 244 + .../liveMng/inc/exports/iot_export_mqtt.h | 360 + .../liveMng/inc/exports/iot_export_ota.h | 240 + .../liveMng/inc/exports/iot_export_reset.h | 8 + .../liveMng/inc/exports/iot_export_shadow.h | 246 + .../liveMng/inc/exports/iot_export_state.h | 113 + .../inc/exports/iot_export_ticknotify.h | 10 + .../liveMng/inc/exports/iot_export_timer.h | 58 + .../liveMng/inc/exports/linkkit_export.h | 370 + .../inc/exports/linkkit_gateway_export.h | 444 + .../liveMng/inc/imports/iot_import_awss.h | 416 + .../liveMng/inc/imports/iot_import_config.h | 74 + .../liveMng/inc/imports/iot_import_crypt.h | 142 + .../liveMng/inc/imports/iot_import_dtls.h | 133 + .../liveMng/inc/imports/iot_import_kv.h | 33 + .../liveMng/inc/imports/iot_import_ota.h | 49 + .../liveMng/inc/imports/iot_import_product.h | 166 + .../liveMng/inc/imports/iot_import_tcp.h | 65 + .../liveMng/inc/imports/iot_import_tls.h | 91 + .../liveMng/inc/imports/iot_import_udp.h | 189 + .../sf_app/component/liveMng/inc/iot_export.h | 358 + .../sf_app/component/liveMng/inc/iot_import.h | 537 + .../component/liveMng/inc/link_visual_api.h | 412 + .../component/liveMng/inc/link_visual_enum.h | 275 + .../liveMng/inc/link_visual_struct.h | 262 + .../component/liveMng/inc/linkkit_client.h | 44 + .../component/liveMng/inc/linkvisual_client.h | 55 + .../component/liveMng/inc/sdk_assistant.h | 33 + .../sf_app/component/liveMng/inc/sf_liveMng.h | 30 + .../sf_app/component/liveMng/src/BAKMakefile | 25 + .../sf_app/component/liveMng/src/Makefile | 25 + .../component/liveMng/src/linkkit_client.c | 497 + .../component/liveMng/src/linkvisual_client.c | 479 + .../component/liveMng/src/sdk_assistant.c | 102 + .../sf_app/component/liveMng/src/sf_liveMng.c | 204 + .../component/liveMng/src/sf_venc_stream.c | 221 + .../source/sf_app/component/nfcMng/Makefile | 11 + .../component/nfcMng/inc/dev_info_ctrl.h | 43 + .../sf_app/component/nfcMng/inc/mbedtls.h | 25941 ++ .../sf_app/component/nfcMng/inc/sf_aes.h | 34 + .../sf_app/component/nfcMng/inc/sf_dev_info.h | 69 + .../sf_app/component/nfcMng/inc/sf_nfc_dev.h | 67 + .../component/nfcMng/inc/sf_nfc_setting.h | 59 + .../sf_app/component/nfcMng/inc/sf_qrutils.h | 46 + .../sf_app/component/nfcMng/src/sf_dev_info.c | 544 + .../sf_app/component/nfcMng/src/sf_nfc_dev.c | 317 + .../component/nfcMng/src/sf_nfc_setting.c | 202 + .../sf_app/component/updataMng/Makefile | 11 + .../sf_app/component/updataMng/inc/sf_md5.h | 35 + .../component/updataMng/inc/sf_otamng.h | 67 + .../sf_app/component/updataMng/src/sf_md5.c | 349 + .../component/updataMng/src/sf_otamng.c | 634 + .../sf_app/output/lib/static/lib4gMng.a | Bin 0 -> 107766 bytes .../sf_app/output/lib/static/libcjson.a | Bin 0 -> 39756 bytes .../sf_app/output/lib/static/libdataMng.a | Bin 0 -> 23916 bytes .../sf_app/output/lib/static/libiot_hal.a | Bin 0 -> 55898 bytes .../sf_app/output/lib/static/libiot_sdk.a | Bin 0 -> 450448 bytes .../sf_app/output/lib/static/libiot_tls.a | Bin 0 -> 195428 bytes .../output/lib/static/liblink_visual_device.a | Bin 0 -> 2323520 bytes .../sf_app/output/obj/4gMng/sf_eg91_gps.d | 10 + .../sf_app/output/obj/4gMng/sf_eg91_gps.o | Bin 0 -> 15616 bytes .../sf_app/output/obj/4gMng/sf_eg91_server.d | 12 + .../sf_app/output/obj/4gMng/sf_eg91_server.o | Bin 0 -> 28036 bytes .../sf_app/output/obj/4gMng/sf_eg91_sim.d | 11 + .../sf_app/output/obj/4gMng/sf_eg91_sim.o | Bin 0 -> 39184 bytes .../sf_app/output/obj/4gMng/sf_module.d | 11 + .../sf_app/output/obj/4gMng/sf_module.o | Bin 0 -> 2276 bytes .../sf_app/output/obj/4gMng/sf_opera_adapt.d | 9 + .../sf_app/output/obj/4gMng/sf_opera_adapt.o | Bin 0 -> 21244 bytes .../sf_app/output/obj/dataMng/sf_data_proc.d | 8 + .../sf_app/output/obj/dataMng/sf_data_proc.o | Bin 0 -> 3056 bytes .../sf_app/output/obj/dataMng/sf_transdata1.d | 9 + .../sf_app/output/obj/dataMng/sf_transdata1.o | Bin 0 -> 19452 bytes .../source/sf_app/sample/test/main.c | 48 + code/application/source/sf_app/sf_app | Bin 5132 -> 0 bytes code/application/source/sf_app/sf_app.sym | 32 - .../vendor/isp/configs/dtsi/os05b10_ae_0.dtsi | 2 +- .../vendor/isp/configs/dtsi/os05b10_iq_0.dtsi | 10 +- .../isp/configs/dtsi/os05b10_iq_0_cap.dtsi | 12 +- code/hdal/vendor/output/libvendor_ai2_pub.a | Bin 141072 -> 141072 bytes code/hdal/vendor/output/libvendor_ai2_pub2.a | Bin 177630 -> 177630 bytes code/lib/source/sifar/Makefile | 22 +- .../source/sifar/code/include/sf_base64.h.bak | 25 + .../source/sifar/code/include/sf_battery.h | 4 +- .../{sf_hal_ttyusb.h => sf_hal_ttyusb.h.bak} | 3 +- code/lib/source/sifar/code/include/sf_inc.h | 10 +- .../code/include/{sf_log.h => sf_log.h.bak} | 5 +- code/lib/source/sifar/code/include/sf_mcu.h | 2 + ...message_queue.h => sf_message_queue.h.bak} | 3 + .../{sf_share_mem.h => sf_share_mem.h.bak} | 3 +- code/lib/source/sifar/code/include/sf_sim.h | 7 +- .../code/include/{sf_type.h => sf_type.h.bak} | 5 + .../sifar/code/source/common/sf_base64.c.bak | 145 + .../sifar/code/source/common/sf_battery.c | 3 +- .../sifar/code/source/common/sf_common.c | 5 +- ...message_queue.c => sf_message_queue.c.bak} | 2 +- .../{sf_share_mem.c => sf_share_mem.c.bak} | 0 .../source/debug/{sf_log.c => sf_log.c.bak} | 0 .../sifar/code/source/mcu/sf_mcu_client.c | 73 + .../{sf_hal_ttyusb.c => sf_hal_ttyusb.c.bak} | 0 .../nvt-info.dtsi | 2 +- .../cardv/SrcCode/FastFlow/flow_preview.c | 175 +- .../source/cardv/SrcCode/PrjCfg_Default.h | 4 + .../cardv/SrcCode/PrjCfg_HUNTING_S530.h | 1 + .../cardv/SrcCode/UIApp/MovieFast/MovieFast.c | 12 +- .../SrcCode/UIApp/MovieStamp/MovieStamp.c | 11 +- .../SrcCode/UIApp/MovieStamp/MovieStamp.h | 2 +- .../cardv/SrcCode/UIApp/PhotoFast/PhotoFast.c | 155 +- .../cardv/SrcCode/UIApp/PhotoFast/PhotoFast.h | 6 + .../UIApp/PhotoFast/PhotoFastCapDateImprint.c | 15 +- .../UIApp/PhotoFast/PhotoFastSliceEncode.c | 1 + .../UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h | 2 +- .../UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c | 24 + .../UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h | 11 +- .../driver/na51089/source/mcu/sf_mcu_dev.c | 31 + .../vendor/isp/configs/dtsi/os05b10_ae_0.dtsi | 4 +- .../vendor/isp/configs/dtsi/os05b10_iq_0.dtsi | 10 +- .../isp/configs/dtsi/os05b10_iq_0_cap.dtsi | 12 +- 264 files changed, 504169 insertions(+), 228 deletions(-) create mode 100755 .vscode/settings.json create mode 100755 S530_VS.sln create mode 100755 S530_VS.vcxproj create mode 100755 S530_VS.vcxproj.filters create mode 100755 S530_VS.vcxproj.user create mode 100755 code/application/source/sf_app/build/cardv_inc.mk create mode 100755 code/application/source/sf_app/build/config.mk create mode 100755 code/application/source/sf_app/build/inc.mk create mode 100755 code/application/source/sf_app/build/modbuild.mk create mode 100755 code/application/source/sf_app/code/include/HMACSHA.h create mode 100755 code/application/source/sf_app/code/include/aos_util.h create mode 100755 code/application/source/sf_app/code/include/apr.h create mode 100755 code/application/source/sf_app/code/include/apr_errno.h create mode 100755 code/application/source/sf_app/code/include/apr_general.h create mode 100755 code/application/source/sf_app/code/include/apr_lib.h create mode 100755 code/application/source/sf_app/code/include/apr_pools.h create mode 100755 code/application/source/sf_app/code/include/apr_sha1.h create mode 100755 code/application/source/sf_app/code/include/apr_strings.h create mode 100755 code/application/source/sf_app/code/include/apr_want.h create mode 100755 code/application/source/sf_app/code/include/apr_xlate.h create mode 100755 code/application/source/sf_app/code/include/apu.h create mode 100755 code/application/source/sf_app/code/include/apu_config.h create mode 100755 code/application/source/sf_app/code/include/bitstream.h create mode 100755 code/application/source/sf_app/code/include/cJSON.h create mode 100755 code/application/source/sf_app/code/include/mask.h create mode 100755 code/application/source/sf_app/code/include/mbedtls.h create mode 100755 code/application/source/sf_app/code/include/mmask.h create mode 100755 code/application/source/sf_app/code/include/mqrspec.h create mode 100755 code/application/source/sf_app/code/include/qrenc.h create mode 100755 code/application/source/sf_app/code/include/qrencode.h create mode 100755 code/application/source/sf_app/code/include/qrencode_inner.h create mode 100755 code/application/source/sf_app/code/include/qrinput.h create mode 100755 code/application/source/sf_app/code/include/qrspec.h create mode 100755 code/application/source/sf_app/code/include/rscode.h create mode 100755 code/application/source/sf_app/code/include/sf_aes.h rename code/{lib/source/sifar => application/source/sf_app}/code/include/sf_base64.h (100%) create mode 100755 code/application/source/sf_app/code/include/sf_bmp.h create mode 100755 code/application/source/sf_app/code/include/sf_commMng.h create mode 100755 code/application/source/sf_app/code/include/sf_commu_mcu.h create mode 100755 code/application/source/sf_app/code/include/sf_commu_mcu_reg.h create mode 100755 code/application/source/sf_app/code/include/sf_dataMng.h create mode 100755 code/application/source/sf_app/code/include/sf_datahttp.h create mode 100755 code/application/source/sf_app/code/include/sf_debug.h create mode 100755 code/application/source/sf_app/code/include/sf_dev_other.h create mode 100755 code/application/source/sf_app/code/include/sf_dev_usb.h create mode 100755 code/application/source/sf_app/code/include/sf_device.h create mode 100755 code/application/source/sf_app/code/include/sf_eg91_gps.h create mode 100755 code/application/source/sf_app/code/include/sf_eg91_server.h create mode 100755 code/application/source/sf_app/code/include/sf_eg91_sim.h create mode 100755 code/application/source/sf_app/code/include/sf_fileMng.h create mode 100755 code/application/source/sf_app/code/include/sf_hal_gpio.h create mode 100755 code/application/source/sf_app/code/include/sf_hal_ttyusb.h create mode 100755 code/application/source/sf_app/code/include/sf_http_server.h create mode 100755 code/application/source/sf_app/code/include/sf_keymng.h create mode 100755 code/application/source/sf_app/code/include/sf_ledmng.h create mode 100755 code/application/source/sf_app/code/include/sf_log.h create mode 100755 code/application/source/sf_app/code/include/sf_message_queue.h create mode 100755 code/application/source/sf_app/code/include/sf_module.h create mode 100755 code/application/source/sf_app/code/include/sf_opera_adapt.h create mode 100755 code/application/source/sf_app/code/include/sf_param_common.h create mode 100755 code/application/source/sf_app/code/include/sf_param_enum.h create mode 100755 code/application/source/sf_app/code/include/sf_param_struct.h create mode 100755 code/application/source/sf_app/code/include/sf_qrcode.h create mode 100755 code/application/source/sf_app/code/include/sf_qrutils.h create mode 100755 code/application/source/sf_app/code/include/sf_storeMng.h create mode 100755 code/application/source/sf_app/code/include/sf_systemMng.h create mode 100755 code/application/source/sf_app/code/include/sf_transdata1.h create mode 100755 code/application/source/sf_app/code/include/sf_type.h create mode 100755 code/application/source/sf_app/code/include/sha256.h create mode 100755 code/application/source/sf_app/code/include/split.h create mode 100755 code/application/source/sf_app/code/source/4gMng/sf_eg91_gps.c create mode 100755 code/application/source/sf_app/code/source/4gMng/sf_eg91_server.c create mode 100755 code/application/source/sf_app/code/source/4gMng/sf_eg91_sim.c create mode 100755 code/application/source/sf_app/code/source/4gMng/sf_http_server.c create mode 100755 code/application/source/sf_app/code/source/4gMng/sf_module.c create mode 100755 code/application/source/sf_app/code/source/4gMng/sf_opera_adapt.c delete mode 100644 code/application/source/sf_app/code/source/app/sf_app.o create mode 100755 code/application/source/sf_app/code/source/app/sf_device.c delete mode 100755 code/application/source/sf_app/code/source/app/sf_test.c delete mode 100644 code/application/source/sf_app/code/source/app/sf_test.o create mode 100755 code/application/source/sf_app/code/source/commMng/sf_message_queue.c create mode 100755 code/application/source/sf_app/code/source/commMng/sf_share_mem.c create mode 100755 code/application/source/sf_app/code/source/dataMng/sf_dataMng.c create mode 100755 code/application/source/sf_app/code/source/dataMng/sf_datahttp.c create mode 100755 code/application/source/sf_app/code/source/dataMng/sf_transdata1.c create mode 100755 code/application/source/sf_app/code/source/debugMng/sf_debug.c create mode 100755 code/application/source/sf_app/code/source/devMng/sf_dev_other.c create mode 100755 code/application/source/sf_app/code/source/devMng/sf_dev_usb.c create mode 100755 code/application/source/sf_app/code/source/devMng/sf_keymng.c create mode 100755 code/application/source/sf_app/code/source/devMng/sf_ledmng.c create mode 100755 code/application/source/sf_app/code/source/fileMng/cJSON.c create mode 100755 code/application/source/sf_app/code/source/fileMng/sf_fileMng.c create mode 100755 code/application/source/sf_app/code/source/gpio/sf_hal_gpio.c create mode 100755 code/application/source/sf_app/code/source/logMng/sf_log.c create mode 100755 code/application/source/sf_app/code/source/paramMng/sf_param_common.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/bitstream.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/mask.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/mmask.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/mqrspec.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/qrenc.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/qrencode.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/qrinput.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/qrspec.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/rscode.c rename code/{lib/source/sifar/code/source/common => application/source/sf_app/code/source/qrcodeMng}/sf_base64.c (100%) create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/sf_bmp.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/sf_qrcode.c create mode 100755 code/application/source/sf_app/code/source/qrcodeMng/split.c create mode 100755 code/application/source/sf_app/code/source/signatureMng/HMACSHA.c create mode 100755 code/application/source/sf_app/code/source/signatureMng/aos_util.c create mode 100755 code/application/source/sf_app/code/source/signatureMng/apr_sha1.c create mode 100755 code/application/source/sf_app/code/source/signatureMng/sha256.c create mode 100755 code/application/source/sf_app/code/source/storeMng/sf_storeMng.c create mode 100755 code/application/source/sf_app/code/source/systemMng/sf_commu_mcu.c create mode 100755 code/application/source/sf_app/code/source/systemMng/sf_commu_mcu_reg.c create mode 100755 code/application/source/sf_app/code/source/systemMng/sf_systemMng.c create mode 100755 code/application/source/sf_app/code/source/ttyusb/sf_hal_ttyusb.c create mode 100755 code/application/source/sf_app/code/source/utils/mbedtls.c create mode 100755 code/application/source/sf_app/code/source/utils/sf_aes.c create mode 100755 code/application/source/sf_app/code/source/utils/sf_qrutils.c create mode 100644 code/application/source/sf_app/code/source/utils/sf_qrutils.o create mode 100755 code/application/source/sf_app/component/Makefile create mode 100755 code/application/source/sf_app/component/liveMng/Makefile create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/aiot_authorize_api.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_awss.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_coap.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_compat.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_diagnosis.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_errno.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_event.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_guider.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2_stream.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_linkkit.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_mqtt.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ota.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_reset.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_shadow.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_state.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ticknotify.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/iot_export_timer.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/linkkit_export.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/exports/linkkit_gateway_export.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_awss.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_config.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_crypt.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_dtls.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_kv.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_ota.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_product.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tcp.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tls.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/imports/iot_import_udp.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/iot_export.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/iot_import.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/link_visual_api.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/link_visual_enum.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/link_visual_struct.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/linkkit_client.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/linkvisual_client.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/sdk_assistant.h create mode 100755 code/application/source/sf_app/component/liveMng/inc/sf_liveMng.h create mode 100755 code/application/source/sf_app/component/liveMng/src/BAKMakefile create mode 100755 code/application/source/sf_app/component/liveMng/src/Makefile create mode 100755 code/application/source/sf_app/component/liveMng/src/linkkit_client.c create mode 100755 code/application/source/sf_app/component/liveMng/src/linkvisual_client.c create mode 100755 code/application/source/sf_app/component/liveMng/src/sdk_assistant.c create mode 100755 code/application/source/sf_app/component/liveMng/src/sf_liveMng.c create mode 100755 code/application/source/sf_app/component/liveMng/src/sf_venc_stream.c create mode 100755 code/application/source/sf_app/component/nfcMng/Makefile create mode 100755 code/application/source/sf_app/component/nfcMng/inc/dev_info_ctrl.h create mode 100755 code/application/source/sf_app/component/nfcMng/inc/mbedtls.h create mode 100755 code/application/source/sf_app/component/nfcMng/inc/sf_aes.h create mode 100755 code/application/source/sf_app/component/nfcMng/inc/sf_dev_info.h create mode 100755 code/application/source/sf_app/component/nfcMng/inc/sf_nfc_dev.h create mode 100755 code/application/source/sf_app/component/nfcMng/inc/sf_nfc_setting.h create mode 100755 code/application/source/sf_app/component/nfcMng/inc/sf_qrutils.h create mode 100755 code/application/source/sf_app/component/nfcMng/src/sf_dev_info.c create mode 100755 code/application/source/sf_app/component/nfcMng/src/sf_nfc_dev.c create mode 100755 code/application/source/sf_app/component/nfcMng/src/sf_nfc_setting.c create mode 100755 code/application/source/sf_app/component/updataMng/Makefile create mode 100755 code/application/source/sf_app/component/updataMng/inc/sf_md5.h create mode 100755 code/application/source/sf_app/component/updataMng/inc/sf_otamng.h create mode 100755 code/application/source/sf_app/component/updataMng/src/sf_md5.c create mode 100755 code/application/source/sf_app/component/updataMng/src/sf_otamng.c create mode 100755 code/application/source/sf_app/output/lib/static/lib4gMng.a create mode 100755 code/application/source/sf_app/output/lib/static/libcjson.a create mode 100755 code/application/source/sf_app/output/lib/static/libdataMng.a create mode 100755 code/application/source/sf_app/output/lib/static/libiot_hal.a create mode 100755 code/application/source/sf_app/output/lib/static/libiot_sdk.a create mode 100755 code/application/source/sf_app/output/lib/static/libiot_tls.a create mode 100755 code/application/source/sf_app/output/lib/static/liblink_visual_device.a create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.d create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.o create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_eg91_server.d create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_eg91_server.o create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.d create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.o create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_module.d create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_module.o create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.d create mode 100755 code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.o create mode 100755 code/application/source/sf_app/output/obj/dataMng/sf_data_proc.d create mode 100755 code/application/source/sf_app/output/obj/dataMng/sf_data_proc.o create mode 100755 code/application/source/sf_app/output/obj/dataMng/sf_transdata1.d create mode 100755 code/application/source/sf_app/output/obj/dataMng/sf_transdata1.o create mode 100755 code/application/source/sf_app/sample/test/main.c delete mode 100755 code/application/source/sf_app/sf_app delete mode 100644 code/application/source/sf_app/sf_app.sym create mode 100755 code/lib/source/sifar/code/include/sf_base64.h.bak rename code/lib/source/sifar/code/include/{sf_hal_ttyusb.h => sf_hal_ttyusb.h.bak} (95%) rename code/lib/source/sifar/code/include/{sf_log.h => sf_log.h.bak} (96%) rename code/lib/source/sifar/code/include/{sf_message_queue.h => sf_message_queue.h.bak} (93%) rename code/lib/source/sifar/code/include/{sf_share_mem.h => sf_share_mem.h.bak} (94%) rename code/lib/source/sifar/code/include/{sf_type.h => sf_type.h.bak} (93%) create mode 100755 code/lib/source/sifar/code/source/common/sf_base64.c.bak rename code/lib/source/sifar/code/source/common/{sf_message_queue.c => sf_message_queue.c.bak} (98%) rename code/lib/source/sifar/code/source/common/{sf_share_mem.c => sf_share_mem.c.bak} (100%) rename code/lib/source/sifar/code/source/debug/{sf_log.c => sf_log.c.bak} (100%) rename code/lib/source/sifar/code/source/module/{sf_hal_ttyusb.c => sf_hal_ttyusb.c.bak} (100%) diff --git a/.gitignore b/.gitignore index 0bcdf3af4..21f260211 100755 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ modules.order .tmp_versions Module.symvers +/.vs diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100755 index 000000000..9a831d20b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.associations": { + "sf_param_common.h": "c", + "sf_filemng.h": "c", + "hmacsha.h": "c", + "stdio.h": "c", + "sf_hal_ttyusb.h": "c", + "type.h": "c", + "sf_commu_mcu_reg.h": "c" + } +} \ No newline at end of file diff --git a/S530_VS.sln b/S530_VS.sln new file mode 100755 index 000000000..cb0709463 --- /dev/null +++ b/S530_VS.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33530.505 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "S530_VS", "S530_VS.vcxproj", "{956E88C5-C345-403E-ABC3-537D4B4CB4B7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Debug|x64.ActiveCfg = Debug|x64 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Debug|x64.Build.0 = Debug|x64 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Debug|x86.ActiveCfg = Debug|Win32 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Debug|x86.Build.0 = Debug|Win32 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Release|x64.ActiveCfg = Release|x64 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Release|x64.Build.0 = Release|x64 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Release|x86.ActiveCfg = Release|Win32 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BF83FDA2-3222-4B3A-9500-DE8DF6048A07} + EndGlobalSection +EndGlobal diff --git a/S530_VS.vcxproj b/S530_VS.vcxproj new file mode 100755 index 000000000..18b2a5c76 --- /dev/null +++ b/S530_VS.vcxproj @@ -0,0 +1,84203 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + {956E88C5-C345-403E-ABC3-537D4B4CB4B7} + Win32Proj + + + + Application + true + v143 + + + Application + false + v143 + + + Application + true + v143 + + + Application + false + v143 + + + + + + + + + + + + + + + + + + + + + true + + + true + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Console + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Console + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/S530_VS.vcxproj.filters b/S530_VS.vcxproj.filters new file mode 100755 index 000000000..1337f1b0d --- /dev/null +++ b/S530_VS.vcxproj.filters @@ -0,0 +1,252301 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/S530_VS.vcxproj.user b/S530_VS.vcxproj.user new file mode 100755 index 000000000..0f14913f3 --- /dev/null +++ b/S530_VS.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build/.nvt_modelcfg b/build/.nvt_modelcfg index 1d106fb0a..5687ccfbf 100644 --- a/build/.nvt_modelcfg +++ b/build/.nvt_modelcfg @@ -32,7 +32,7 @@ EMBMEM = EMBMEM_SPI_NOR FW_TYPE = FW_TYPE_PARTIAL UI_STYLE = UI_STYLE_LVGL NVT_CFG_APP_EXTERNAL = hostapd wireless_tool iperf-3 wpa_supplicant dhd_priv -NVT_CFG_APP = mem cardv memcpy isp_demon +NVT_CFG_APP = mem cardv memcpy isp_demon sf_app NVT_ROOTFS_ETC = NVT_BINARY_FILE_STRIP = yes NVT_CFG_KERNEL_CFG = na51089_evb_cardv_defconfig_release diff --git a/code/application/source/cardv/OutputImg.mk b/code/application/source/cardv/OutputImg.mk index 79a4477af..fd640e120 100755 --- a/code/application/source/cardv/OutputImg.mk +++ b/code/application/source/cardv/OutputImg.mk @@ -68,7 +68,7 @@ C_LDFLAGS = \ LDSCRIPT = $(MODULE_NAME).lds LDS_EXTERN = extern.lds OUTPUT_NAME = $(OUTPUT_DIR)/cardv -#OUTPUT2_NAME = $(OUTPUT_DIR)/sf_app +#OUTPUT2_NAME = $(OUTPUT_DIR)/sifar_app IMG_NAME = $(OUTPUT_DIR)/$(MODULE_NAME).img MAP_NAME = $(OUTPUT_DIR)/$(MODULE_NAME).map SYM_NAME = $(OUTPUT_DIR)/$(MODULE_NAME).sym @@ -368,7 +368,7 @@ cim: $(DTB) $(OBJ) clean: @rm -rf $(OBJ) $(MAIN_C:.c=.o) $(LDS_EXTERN) $(DTB) $(OUTPUT_DIR) -install: $(OUTPUT_NAME) $(OUTPUT_APPFS) +install: $(OUTPUT_NAME) $(OUTPUT_APPFS) @mkdir -p $(INSTALL_DIR) @cp -avf $(OUTPUT_NAME) $(INSTALL_DIR) @cp -avf $(OUTPUT_NAME) $(ROOTFS_DIR)/rootfs/usr/bin diff --git a/code/application/source/cardv/SrcCode/Startup/sifar_app.c b/code/application/source/cardv/SrcCode/Startup/sifar_app.c index c2f71144c..6e0f0448b 100755 --- a/code/application/source/cardv/SrcCode/Startup/sifar_app.c +++ b/code/application/source/cardv/SrcCode/Startup/sifar_app.c @@ -13,6 +13,7 @@ int main(int argc, char *argv[]) gpio_direction_input(C_GPIO(10)); + return 0; } diff --git a/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c b/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c index 14b7da0ab..ba4b3a2ff 100755 --- a/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c +++ b/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c @@ -21,6 +21,7 @@ #if MOVIE_ISP_LOG #include "vendor_isp.h" +#include "sf_mcu.h" #endif //#NT#2016/10/17#Bin Xiao -end #define __MODULE__ MovieStamp @@ -276,6 +277,9 @@ static void MovieStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) AET_STATUS_INFO ae_status = {0}; AWBT_STATUS awb_status = {0}; IQT_WDR_PARAM wdr = {0}; + //sf_mcu_power_on_para_get(SF_MCU_POWERON); + UINT16 AD_Value; + AD_Value = sf_mcu_get_irshtter(); id = 0; ae_status.id = id; @@ -285,7 +289,8 @@ id = 0; wdr.id = id; vendor_isp_get_iq(IQT_ITEM_WDR_PARAM, &wdr); - snprintf(Buf, BufLen, "%3d %4d %4d %6d %6d %4d %4d %d %4d %4d %4d\0", + snprintf(Buf, BufLen, "%d %3d %3d %3d %6d %6d %3d %3d %d %3d %3d %4d %d\0", + ae_status.status_info.state_adj, ae_status.status_info.lv/100000, ae_status.status_info.lum, ae_status.status_info.expect_lum, @@ -296,7 +301,8 @@ id = 0; wdr.wdr.enable, awb_status.status.cur_r_gain, awb_status.status.cur_b_gain, - awb_status.status.cur_ct + awb_status.status.cur_ct, + AD_Value ); //DBG_DUMP("isp Buf=%s\r\n",Buf); diff --git a/code/application/source/cardv/SrcCode/UIApp/Photo/UIAppPhoto_Exe.c b/code/application/source/cardv/SrcCode/UIApp/Photo/UIAppPhoto_Exe.c index 6591229d3..499bf12b4 100755 --- a/code/application/source/cardv/SrcCode/UIApp/Photo/UIAppPhoto_Exe.c +++ b/code/application/source/cardv/SrcCode/UIApp/Photo/UIAppPhoto_Exe.c @@ -29,6 +29,7 @@ #include "UIApp/AppDisp_PipView.h" #include #include "vendor_videocapture.h" +#include "sf_mcu.h" #define THIS_DBGLVL 2 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER @@ -1403,11 +1404,11 @@ void PhotoStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) AWBT_STATUS awb_status = {0}; //IQT_WDR_PARAM wdr = {0}; HD_RESULT hd_ret; - +UINT16 AD_Value; if ((hd_ret = vendor_isp_init()) != HD_OK) { DBG_ERR("vendor_isp_init() failed(%d)\r\n", hd_ret); } - +AD_Value = sf_mcu_get_irshtter(); ae_status.id = 0; vendor_isp_get_ae(AET_ITEM_STATUS, &ae_status); awb_status.id = 0; @@ -1415,7 +1416,8 @@ void PhotoStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) /*wdr.id = id; vendor_isp_get_iq(IQT_ITEM_WDR_PARAM, &wdr); */ - snprintf(Buf, BufLen, "%3d %4d %4d %6d %6d %4d %4d %4d %4d %4d\0", + snprintf(Buf, BufLen, "%d %3d %3d %3d %6d %6d %4d %4d %3d %3d %4d %d\0", + ae_status.status_info.state_adj, ae_status.status_info.lv/100000, ae_status.status_info.lum, ae_status.status_info.expect_lum, @@ -1426,9 +1428,10 @@ void PhotoStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) //wdr.wdr.enable, awb_status.status.cur_r_gain, awb_status.status.cur_b_gain, - awb_status.status.cur_ct + awb_status.status.cur_ct, + AD_Value ); -// DBG_ERR("isp Buf=%s\r\n",Buf); + DBG_ERR("isp Buf=%s\r\n",Buf); if ((hd_ret = vendor_isp_uninit()) != HD_OK) { DBG_ERR("vendor_isp_uninit() failed(%d)\r\n", hd_ret); } @@ -5931,11 +5934,13 @@ INT32 PhotoExe_Preview_SliceEncode_CB2(void* user_data) MEM_RANGE pri_jpg = {.addr = slice_encode_primary_info->bs_buf_mem_info.va + CFG_JPG_HEADER_SIZE, .size = slice_encode_primary_info->bs_buf_mem_info.used_size}; MEM_RANGE scr_jpg = {.addr = slice_encode_screennail_info->bs_buf_mem_info.va, .size = slice_encode_screennail_info->bs_buf_mem_info.used_size}; MEM_RANGE dst_jpg_file = { 0 }; + DBG_WRN(" EXIF\r\n"); /* exif */ ExifVendor_Write0thIFD(EXIF_HDL_ID_1); ExifVendor_WriteExifIFD(EXIF_HDL_ID_1); ExifVendor_Write0thIntIFD(EXIF_HDL_ID_1); + ExifVendor_WriteGPSIFD(EXIF_HDL_ID_1); if (EXIF_CreateExif(EXIF_HDL_ID_1, &exif_data, &thumb_jpg) != EXIF_ER_OK) { DBG_ERR("Create Exif fail\r\n"); exif_data.size = 0; diff --git a/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h b/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h index f04145b9a..1978be37a 100755 --- a/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h +++ b/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h @@ -166,7 +166,7 @@ #endif #define DEFAULT_ETHCAM_TX_IP_ADDR 0 //0xc00a8c0 -#define DEFAULT_BOOT_WORK_MODE SF_CAM_MODE_PHOTO_VIDEO//SF_CAM_MODE_PHOTO +#define DEFAULT_BOOT_WORK_MODE SF_CAM_MODE_PHOTO_VIDEO// #define DEFAULT_SF_CAMID SF_CAMID_OFF #define DEFAULT_FLASH_LED SF_FLASH_LED_HIGH #define DEFAULT_NIGHT_MODE SF_NIGHT_MODE_MIN_BLUR//SF_NIGHT_MODE_BALANCED diff --git a/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c b/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c index 84cde1297..b0cd6e22d 100755 --- a/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c +++ b/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c @@ -1477,6 +1477,7 @@ void SysSetFixedFlagSysInit(void) void SysResetFlag(void) { + UIMenuStoreInfo *puiPara = sf_ui_para_get(); // Set system flag default value here // Photo SysSetFlag(FL_PHOTO_SIZE, DEFAULT_PHOTO_SIZE); @@ -1614,9 +1615,33 @@ void SysResetFlag(void) SysSetFlag(PirSwitch, DEFAULT_PIR_SWITCH); SysSetFlag(PirSensitivity, DEFAULT_PIR_SENSITIVITY); SysSetFlag(PirDelaySwitch, DEFAULT_PIR_DELAY_SWITCH); + SysSetFlag(TimelapseSwitch, DEFAULT_TIMELAPSE_SWITCH); + if(SysGetFlag(TimelapseSwitch)) + { + puiPara->TimelapseTime.Hour = 0; + puiPara->TimelapseTime.Min = 0; + puiPara->TimelapseTime.Sec = 5; + } + SysSetFlag(WorkTime1Switch, DEFAULT_WORKTIME_SWITCH); + if(SysGetFlag(WorkTime1Switch)) + { + puiPara->WorkTime[0].StartTime.Hour = 16; + puiPara->WorkTime[0].StartTime.Min = 0; + puiPara->WorkTime[0].StopTime.Hour = 20; + puiPara->WorkTime[0].StopTime.Min = 0; + } + SysSetFlag(WorkTime2Switch, DEFAULT_WORKTIME_SWITCH); + if(SysGetFlag(WorkTime2Switch)) + { + puiPara->WorkTime[1].StartTime.Hour = 5; + puiPara->WorkTime[1].StartTime.Min = 0; + puiPara->WorkTime[1].StopTime.Hour = 8; + puiPara->WorkTime[1].StopTime.Min = 0; + } + SysSetFlag(SimAutoSwitch, DEFAULT_SIM_AUTO_SWITCH); SysSetFlag(SendMaxNum, DEFAULT_SEND_MAX_NUM); SysSetFlag(GprsMode, DEFAULT_GPRS_MODE); @@ -1667,6 +1692,8 @@ void SysResetFlag(void) SysSetFlag(TimeSend4Switch, DEFAULT_TIMESEND4_SWITCH); //sf_set_pir_sensitivity(7); #endif + + printf("%s:%d sifar para e\n", __FUNCTION__, __LINE__); diff --git a/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h b/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h index 8f0ab882e..e74df2e72 100755 --- a/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h +++ b/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h @@ -7,9 +7,16 @@ #endif //============Sifar==============///Payton +#ifndef SF_DATA_UI_TYPE +#define SF_DATA_UI_TYPE + #define SF_TIMER_MAX_NUMBER 2 typedef struct sf_PARA_TIME_S -{ +{ + UINT16 Year; + UINT16 Mon; + UINT16 Day; + UINT8 Hour; UINT8 Min; UINT8 Sec; @@ -20,6 +27,7 @@ typedef struct sf_WORKTIME_S SF_PARA_TIME_S StartTime; SF_PARA_TIME_S StopTime; } SF_WORKTIME_S; +#endif //============Sifar==============///Payton /** diff --git a/code/application/source/sf_app/MakeConfig.mk b/code/application/source/sf_app/MakeConfig.mk index f4e4c3386..d49d2faad 100755 --- a/code/application/source/sf_app/MakeConfig.mk +++ b/code/application/source/sf_app/MakeConfig.mk @@ -77,3 +77,8 @@ C_PREDEFINED = \ -D_$(TOUCH)_ \ -D_$(NVT_ETHREARCAM)_\ -D_$(NVT_ETHREARCAM_CAPS_COUNT)_\ + -DCFG_MODULE_EG91 \ + -DCFG_COMM_MCU_UART \ + -DCFG_SUPPORT_OTHER_SIM \ + -DCFG_SUPPORT_GPS \ + \ No newline at end of file diff --git a/code/application/source/sf_app/Makefile b/code/application/source/sf_app/Makefile index 267b61097..48beabcdc 100755 --- a/code/application/source/sf_app/Makefile +++ b/code/application/source/sf_app/Makefile @@ -32,6 +32,27 @@ endif SIFAR_DIR = $(LIBRARY_DIR)/source/sifar/code SIFAR_APP_DIR = ./code/include +#LIB DIRs for C_LDFLAGS +EXTRA_LIB_DIR += \ + -L$(LIBC_LIB_DIR) \ + -L$(GCC_LIB_DIR) \ + -L$(STDC_LIB_DIR) \ + -L$(SYSROOT_LIB_DIR) \ + -L$(NVT_HDAL_DIR)/output \ + -L$(NVT_HDAL_DIR)/vendor/output \ + -L$(NVT_HDAL_DIR)/vendor/media/drivers/output/ \ + -L$(NVT_HDAL_DIR)/vendor/isp/drivers/output/ \ + -L$(KDRV_DIR)/output \ + -L$(EXT_DIR)/panel/output \ + -L$(EXT_DIR)/sensor/output \ + -L$(EXT_DIR)/audio/output \ + -L$(KFLOW_DIR)/output \ + -L$(HDAL_SAMPLE_DIR)/output \ + -L$(LIBRARY_DIR)/output \ + -L$(VOS_DRIVER_DIR)/output \ + -L$(NVT_VOS_DIR)/output \ + -L$(NVT_DRIVER_DIR)/output \ + # public includes EXTRA_INCLUDE += \ -I$(NVT_VOS_DIR)/include \ @@ -52,7 +73,6 @@ EXTRA_INCLUDE += \ -I$(KDRV_DIR)/source/kdrv_gfx2d/kdrv_affine/include \ -I$(NVT_HDAL_DIR)/vendor/media/include \ -I$(NVT_HDAL_DIR)/vendor/common/include \ - -I$(SIFAR_DIR)/include \ -I$(SIFAR_APP_DIR) \ # application local includes @@ -84,9 +104,99 @@ EXTRA_INCLUDE += \ #--------- END OF INCs FOR C_CFLAGS --------------------------------------------------- +# kernel, vos, libc, others necessary +EXTRA_LIB = \ + -lgcc \ + -lgcc_s \ + -lc -lgcc \ + -lgcc_s \ + -lrt \ + -lm \ + -l:libstdc++.a \ + -lpthread \ + +# vos +EXTRA_LIB += \ + -l:libvos.a \ + +# hdal, vendor +EXTRA_LIB += \ + -l:libhdal.a \ + -l:libvendor_media.a \ + -l:libvendor_isp.a \ + -l:libprebuilt_isp.a \ + # code/lib EXTRA_LIB += \ - -l:libsifar.a \ + -l:libSxTimer.a \ + -l:libgxgfx.a \ + -l:libnvtuser.a \ + -l:libuicontrol.a \ + -l:libvcontrol.a \ + -l:libappcontrol.a \ + -l:libvf_gfx.a \ + -l:libutility.a \ + -l:libfdt.a \ + -l:libWiFiIpc.a \ + -l:libfiledb.a \ + -l:libDCF.a \ + -l:libFileSys.a \ + -l:libNameRule.a \ + -l:libFsLinux.a \ + -l:libio.a \ + -l:libstrg.a \ + -l:libfileout.a \ + -l:libavfile.a \ + -l:libbsmux.a \ + -l:libnvtlive555.a \ + -l:libLviewNvt.a \ + -l:libgximagefile.a \ + -l:libexif.a \ + -l:libsizeconvert.a \ + -l:libimageapp_common.a \ + -l:libimageapp_moviemulti.a \ + -l:libimageapp_usbmovie.a \ + -l:libimageapp_voice.a \ + -l:libFontConv.a \ + -l:libimageapp_photo.a \ + -l:libmsdcnvt.a \ + -l:libumsd.a \ + -l:libusb2dev.a \ + -l:libimageapp_play.a \ + -l:libplayback.a \ + -l:libpbxfilelist_filedb.a \ + -l:libpbxfilelist_dcf.a \ + -l:libGxVideoFile.a \ + -l:libpbxfile.a \ + -l:libfilein.a \ + -l:libbsdemux.a \ + -l:libimageapp_movieplay.a \ + -l:libusockipc.a \ + -l:libusockcliipc.a \ + -l:libHfsNvt.a \ + -l:libuvac.a \ + -l:libuvcp.a \ + -l:libfwsrv.a \ + -l:libsw_md.a \ + -l:libPStore.a \ + -l:libethcamsocket.a \ + -l:libethsocketcli.a \ + -l:libethsockcliipc.a \ + -l:libethsocket.a \ + -l:libethcamsmi.a \ + -l:libtse.a \ + -l:liblogfile.a \ + +ifeq "$(UI_STYLE)" "UI_STYLE_LVGL" +EXTRA_LIB += \ + -l:liblvgl.a \ + +endif + +EXTRA_LIB += \ + -l:libvendor_ai2.a \ + -l:libvendor_ai2_pub.a \ + -l:libprebuilt_ai.a ####################################################################################### #--------- SOURCEs FOR APPLICATION ---------------------------------------------------# @@ -94,21 +204,81 @@ EXTRA_LIB += \ # system SRC = \ - ./code/source/app/sf_test.c \ - ./code/source/app/sf_app.c + ./code/source/app/sf_device.c \ + ./code/source/app/sf_app.c \ + ./code/source/gpio/sf_hal_gpio.c \ + ./code/source/logMng/sf_log.c \ + ./code/source/commMng/sf_message_queue.c \ + ./code/source/commMng/sf_share_mem.c \ + ./code/source/fileMng/cJSON.c \ + ./code/source/fileMng/sf_fileMng.c \ + ./code/source/signatureMng/aos_util.c \ + ./code/source/signatureMng/apr_sha1.c \ + ./code/source/signatureMng/HMACSHA.c \ + ./code/source/signatureMng/sha256.c \ + ./code/source/paramMng/sf_param_common.c \ + ./code/source/qrcodeMng/bitstream.c \ + ./code/source/qrcodeMng/mask.c \ + ./code/source/qrcodeMng/mmask.c \ + ./code/source/qrcodeMng/mqrspec.c \ + ./code/source/qrcodeMng/qrenc.c \ + ./code/source/qrcodeMng/qrencode.c \ + ./code/source/qrcodeMng/qrinput.c \ + ./code/source/qrcodeMng/qrspec.c \ + ./code/source/qrcodeMng/rscode.c \ + ./code/source/qrcodeMng/sf_base64.c \ + ./code/source/qrcodeMng/sf_bmp.c \ + ./code/source/qrcodeMng/sf_qrcode.c \ + ./code/source/qrcodeMng/split.c \ + ./code/source/storeMng/sf_storeMng.c \ + ./code/source/ttyusb/sf_hal_ttyusb.c \ + ./code/source/4gMng/sf_eg91_gps.c \ + ./code/source/4gMng/sf_eg91_server.c \ + ./code/source/4gMng/sf_eg91_sim.c \ + ./code/source/4gMng/sf_http_server.c \ + ./code/source/4gMng/sf_module.c \ + ./code/source/4gMng/sf_opera_adapt.c \ + ./code/source/dataMng/sf_dataMng.c \ + ./code/source/dataMng/sf_transdata1.c \ + ./code/source/dataMng/sf_datahttp.c \ + ./code/source/systemMng/sf_systemMng.c \ + ./code/source/systemMng/sf_commu_mcu_reg.c \ + ./code/source/systemMng/sf_commu_mcu.c \ + ./code/source/devMng/sf_dev_other.c \ + ./code/source/devMng/sf_dev_usb.c \ + ./code/source/devMng/sf_keymng.c \ + ./code/source/devMng/sf_ledmng.c \ + ./code/source/utils/mbedtls.c \ + ./code/source/utils/sf_aes.c \ + ./code/source/debugMng/sf_debug.c #--------- END OF SOURCEs FOR APPLICATION --------------------------------------------- -include $(NVT_PRJCFG_MODEL_CFG) #--------- ENVIRONMENT SETTING -------------------- INCLUDES = -I$(NVT_HDAL_DIR)/include -I$(LIBRARY_DIR)/include WARNING = -Wall -Wundef -Wsign-compare -Wno-missing-braces -Wstrict-prototypes COMPILE_OPTS = $(INCLUDES) -I. -O2 -fPIC -ffunction-sections -fdata-sections CPPFLAGS = CFLAGS = $(PLATFORM_CFLAGS) $(PRJCFG_CFLAGS) -C_FLAGS = $(COMPILE_OPTS) $(EXTRA_INCLUDE) $(EXTRA_LIB) $(CPPFLAGS) $(CFLAGS) $(WARNING) $(C_PREDEFINED) -LD_FLAGS = -L$(LIBRARY_DIR)/output/lib -Wl,-rpath-link=$(LIBRARY_DIR)/output/lib -lrt +C_FLAGS = $(COMPILE_OPTS) $(EXTRA_INCLUDE) $(EXTRA_LIB_DIR) $(EXTRA_LIB) $(CPPFLAGS) $(CFLAGS) $(WARNING) $(C_PREDEFINED) +LD_FLAGS = $(EXTRA_LIB_DIR) $(EXTRA_LIB) + +C_LDFLAGS = \ + --sysroot=$(SYSROOT_DIR) \ + --eh-frame-hdr \ + -dynamic-linker $(DYNAMIC_LINKER) \ + -X \ + -m armelf_linux_eabi \ + -T $(OUTPUT_DIR)/$(LDSCRIPT) \ + -Map $(MAP_NAME) \ + --start-group \ + $(CRT_OBJ_BEGIN) \ + $(EXTRA_LIB_DIR) \ + $(EXTRA_LIB) \ + $(CRT_OBJ_END) \ + --end-group + #--------- END OF ENVIRONMENT SETTING ------------- #--------- Compiling ------------------- diff --git a/code/application/source/sf_app/build/cardv_inc.mk b/code/application/source/sf_app/build/cardv_inc.mk new file mode 100755 index 000000000..ded6f2546 --- /dev/null +++ b/code/application/source/sf_app/build/cardv_inc.mk @@ -0,0 +1,3 @@ + +INCLUDE_PATH+= -I$(SF_CS_DIR)/common/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/cardv_debug/inc diff --git a/code/application/source/sf_app/build/config.mk b/code/application/source/sf_app/build/config.mk new file mode 100755 index 000000000..0817b6127 --- /dev/null +++ b/code/application/source/sf_app/build/config.mk @@ -0,0 +1,14 @@ + +CUR_DIR_NAME = $(shell pwd |sed 's/^\(.*\)[/]//' ) +CUR_PARENT_DIR_NAME = $(shell cd ./..;pwd|sed 's/^\(.*\)[/]//') + +CFG_4G_ENBLE =y +CFG_LIVE_ENBLE =n +CFG_MODULE_TYPE =EG91 +CFG_COMM_MCU_TYPE =UART +CFG_TRANSDATA_TYPE =HTTP +CFG_DUAL_PROCESS_EN =y + +CFG_CASE_TYPE =T100 +CFG_OTHER_SIM =y +CFG_GPS =y \ No newline at end of file diff --git a/code/application/source/sf_app/build/inc.mk b/code/application/source/sf_app/build/inc.mk new file mode 100755 index 000000000..770f304c6 --- /dev/null +++ b/code/application/source/sf_app/build/inc.mk @@ -0,0 +1,72 @@ +include $(SF_CS_DIR)/build/config.mk +C_FLAGS := +INCLUDE_PATH+= -I$(SF_CS_DIR)/hal/gpio/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/hal/ttyusb/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/logMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/fileMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/commMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/dataMng/common/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/dataMng/datacmd/inc +ifeq ($(CFG_TRANSDATA_TYPE) ,AT) +C_FLAGS += -DCFG_TRANSDATA_AT +else +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/dataMng/datahttp/inc +endif +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/debugMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/paramMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/storeMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/systemMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/qrcodeMng/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/signatureMng/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/devMng/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/nfcMng/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/updataMng/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/utils/inc + +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/4gMng/common/inc +ifeq ($(CFG_MODULE_TYPE) ,EG91) +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/4gMng/EG91/inc +ifneq ($(CFG_TRANSDATA_TYPE) ,AT) +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/4gMng/http/inc +endif +C_FLAGS += -DCFG_MODULE_EG91 +endif + +ifeq ($(CFG_LIVE_ENBLE) ,y) +C_FLAGS += -DCFG_LIVE_ENBLE +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/liveMng/inc +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/liveMng/inc/exports +INCLUDE_PATH+= -I$(SF_CS_DIR)/component/liveMng/inc/imports +endif + +ifeq ($(CFG_CASE_TYPE) ,T100) +INCLUDE_PATH+= -I$(SF_CS_DIR)/app/t100/inc +endif + +ifeq ($(CFG_DUAL_PROCESS_EN) ,y) +INCLUDE_PATH+= -I$(SF_CS_DIR)/../../../../project/release/include +INCLUDE_PATH+= -I$(SF_CS_DIR)/../cardv/inc/mid +endif + +ifeq ($(CFG_COMM_MCU_TYPE) ,IIC) +C_FLAGS += -DCFG_COMM_MCU_IIC +else +C_FLAGS += -DCFG_COMM_MCU_UART +endif + +ifeq ($(CFG_OTHER_SIM) ,y) +C_FLAGS += -DCFG_SUPPORT_OTHER_SIM +endif + +ifeq ($(CFG_GPS) ,y) +C_FLAGS += -DCFG_SUPPORT_GPS +endif diff --git a/code/application/source/sf_app/build/modbuild.mk b/code/application/source/sf_app/build/modbuild.mk new file mode 100755 index 000000000..7d15bb07e --- /dev/null +++ b/code/application/source/sf_app/build/modbuild.mk @@ -0,0 +1,75 @@ + +include $(SF_CS_DIR)/build/inc.mk +include $(PROJECT_DIR)/configs/current.configs +-include $(PROJECT_DIR)/release/$(PRODUCT)/$(CHIP)/$(BOARD)/$(TOOLCHAIN)/toolchain.mk + + +MODULE_NAME ?=$(CUR_DIR_NAME) + +CFLAGS := -Wall -O3 +#-std=c99 +COMPILEDEP = $(CC) -MM "$<" $(INCLUDE_PATH) + +OBJ_DIR := $(SF_CS_DIR)/output/obj/$(MODULE_NAME) + +LIB :=$(SF_CS_DIR)/output/lib/static/lib$(MODULE_NAME).a +SOLIB := $(SF_CS_DIR)/output/lib/dynamic/lib$(MODULE_NAME).so + + +COMPILE = $(CC) $(C_FLAGS) -c "$<" -o "$@" $(INCLUDE_PATH) +SRCS := $(shell find $(SRC_DIR) -name '*.c') +SRCS := $(sort $(SRCS)) + +ifneq ($(CFG_DUAL_PROCESS_EN),y) +SRCS_OMIT := $(shell find $(SRC_DIR) -name 'main.c') +SRCS := $(filter-out $(SRCS_OMIT),$(SRCS)) +endif + +OBJS := $(SRCS:$(SRC_DIR)%.c=$(OBJ_DIR)%.o) +OBJS := $(sort $(OBJS)) +SRC_DEPS := $(OBJS:%.o=%.d) + + +.PHONY: clean $(LIB) all install +all : prepare $(SRC_DEPS) $(OBJS) $(LIB) install + + +prepare: + @echo "";echo "" + @echo -e "\033[31;32m *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \033[0m" + @echo -e "\033[31;32m [COMPILING] `basename $(MODULE_NAME)` ... ... \033[0m" + @echo "" + @mkdir -p $(OBJ_DIR) +$(SRC_DEPS) : $(OBJ_DIR)/%.d : $(SRC_DIR)/%.c + @echo "SRC_DEPS: " $(notdir $@) + set -e;$(COMPILEDEP) > $@.$$$$; \ + sed 's,.*\.o[ :]*,$(@:%.d=%.o) $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ +$(OBJS) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.c + @echo -e "\033[31;32m [$(CC)] \033[0m `basename $<` \033[0m" + $(CC) $(CFLAGS) $(C_FLAGS) -fpic -c $< -o $@ $(INCLUDE_PATH) + @echo -e "\033[31;32m [OK] \033[0m";echo "" + +$(LIB) : $(OBJS) + @echo -e "\033[31;32m [CREATING] \033[0m `basename $(LIB)` \033[0m" + $(AR) -r $@ $(OBJS) + @echo -e "\033[31;32m [OK] \033[0m";echo "" + +$(SOLIB) : $(OBJS) + @echo -e "\033[31;32m [CREATING] \033[0m `basename $(SOLIB)` \033[0m" + @$(CC) -fPIC -shared -o $@ $(OBJS) + @echo -e "\033[31;32m [OK] \033[0m";echo "" + +clean: + @echo " " + @echo "--------------------------------------------" + @echo -e "\033[31;31m [DELETING $(MODULE_NAME) files ......] \033[0m" + @-rm -f $(LIB) + @-rm -f $(SOLIB) + @-rm -f $(SRC_DEPS) + @if [ -n $(OBJ_DIR) ];then rm -rf $(OBJ_DIR);fi + @echo "--------------------------------------------" + @echo " " +install: + @#cp $(SOLIB) $(PROJECT_DIR)/release/$(PRODUCT)/$(CHIP)/common/$(TOOLCHAIN)/$(TOOLCHAIN_VERSION)/ex_libs/dynamic + @#cp $(LIB) $(PROJECT_DIR)/release/$(PRODUCT)/$(CHIP)/common/$(TOOLCHAIN)/$(TOOLCHAIN_VERSION)/ex_libs/static diff --git a/code/application/source/sf_app/code/include/HMACSHA.h b/code/application/source/sf_app/code/include/HMACSHA.h new file mode 100755 index 000000000..d63819806 --- /dev/null +++ b/code/application/source/sf_app/code/include/HMACSHA.h @@ -0,0 +1,19 @@ +#ifndef HMACSHA_H +#define HMACSHA_H +#include "sf_type.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +void amz_signature(UINT8 *signatureStr,UINT32 content_len, UINT8*objectName,UINT8*typestr,UINT8*password,UINT8*bucket,UINT8*region); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + diff --git a/code/application/source/sf_app/code/include/aos_util.h b/code/application/source/sf_app/code/include/aos_util.h new file mode 100755 index 000000000..9f21d5dbe --- /dev/null +++ b/code/application/source/sf_app/code/include/aos_util.h @@ -0,0 +1,41 @@ +#ifndef LIBAOS_UTIL_H +#define LIBAOS_UTIL_H +#include "sf_type.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + + + +#define APR_SHA1_DIGESTSIZE 20 + +/** + * base64 encode bytes. The output buffer must have at least + * ((4 * (inLen + 1)) / 3) bytes in it. Returns the number of bytes written + * to [out]. + */ +int aos_base64_encode(const UINT8 *in, int inLen, UINT8 *out); + +/** + * Compute HMAC-SHA-1 with key [key] and message [message], storing result + * in [hmac] + */ +void HMAC_SHA1(UINT8 hmac[20], const UINT8 *key, int key_len, + const UINT8 *message, int message_len); + +/*void oss_sign_headers(aos_pool_t *p, const aos_string_t *signstr, const aos_string_t *access_key_id, + const aos_string_t *access_key_secret, aos_table_t *headers);*/ + +void oss_sign_headers(); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif diff --git a/code/application/source/sf_app/code/include/apr.h b/code/application/source/sf_app/code/include/apr.h new file mode 100755 index 000000000..a75bc6029 --- /dev/null +++ b/code/application/source/sf_app/code/include/apr.h @@ -0,0 +1,644 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_H +#define APR_H + +/* GENERATED FILE WARNING! DO NOT EDIT apr.h + * + * You must modify apr.hw instead. + * + * And please, make an effort to stub apr.hnw and apr.h.in in the process. + * + * This is the Win32 specific version of apr.h. It is copied from + * apr.hw by the apr.dsp and libapr.dsp projects. + */ + +/** + * @file apr.h + * @brief APR Platform Definitions + * @remark This is a generated header generated from include/apr.h.in by + * ./configure, or copied from include/apr.hw or include/apr.hnw + * for Win32 or Netware by those build environments, respectively. + */ + +/* Make sure we have our platform identifier macro defined we ask for later. + */ +#if defined(_WIN32) && !defined(WIN32) +#define WIN32 1 +#endif + +#if defined(WIN32) || defined(DOXYGEN) + +/* Ignore most warnings (back down to /W3) for poorly constructed headers + */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#pragma warning(push, 3) +#endif + +/* disable or reduce the frequency of... + * C4057: indirection to slightly different base types + * C4075: slight indirection changes (unsigned short* vs short[]) + * C4100: unreferenced formal parameter + * C4127: conditional expression is constant + * C4163: '_rotl64' : not available as an intrinsic function + * C4201: nonstandard extension nameless struct/unions + * C4244: int to char/short - precision loss + * C4514: unreferenced inline function removed + */ +#pragma warning(disable: 4100 4127 4163 4201 4514; once: 4057 4075 4244) + +/* Ignore Microsoft's interpretation of secure development + * and the POSIX string handling API + */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +#pragma warning(disable: 4996) +#endif + +/* Has windows.h already been included? If so, our preferences don't matter, + * but we will still need the winsock things no matter what was included. + * If not, include a restricted set of windows headers to our tastes. + */ +#ifndef _WINDOWS_ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef _WIN32_WINNT + +/* Restrict the server to a subset of Windows XP header files by default + */ +#define _WIN32_WINNT 0x0501 +#endif +#ifndef NOUSER +#define NOUSER +#endif +#ifndef NOMCX +#define NOMCX +#endif +#ifndef NOIME +#define NOIME +#endif +#include +/* + * Add a _very_few_ declarations missing from the restricted set of headers + * (If this list becomes extensive, re-enable the required headers above!) + * winsock headers were excluded by WIN32_LEAN_AND_MEAN, so include them now + */ +#define SW_HIDE 0 +#ifndef _WIN32_WCE +#include +#include +#include +#else +#include +#endif +#endif /* !_WINDOWS_ */ + +/** + * @defgroup APR Apache Portability Runtime library + * @{ + */ +/** + * @defgroup apr_platform Platform Definitions + * @{ + * @warning + * The actual values of macros and typedefs on this page
+ * are platform specific and should NOT be relied upon!
+ */ + +#define APR_INLINE __inline +#define APR_HAS_INLINE 1 +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(__x) +#endif + +#ifndef _WIN32_WCE +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 1 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 1 +#define APR_HAVE_DIRENT_H 0 +#define APR_HAVE_ERRNO_H 1 +#define APR_HAVE_FCNTL_H 1 +#define APR_HAVE_IO_H 1 +#define APR_HAVE_LIMITS_H 1 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#define APR_HAVE_NETINET_SCTP_H 0 +#define APR_HAVE_NETINET_SCTP_UIO_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SEMAPHORE_H 0 +#define APR_HAVE_SIGNAL_H 1 +#define APR_HAVE_STDARG_H 1 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_SYS_IOCTL_H 0 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SIGNAL_H 0 +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SOCKIO_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#define APR_HAVE_SYS_TYPES_H 1 +#define APR_HAVE_SYS_UIO_H 0 +#define APR_HAVE_SYS_UN_H 0 +#define APR_HAVE_SYS_WAIT_H 0 +#define APR_HAVE_TIME_H 1 +#define APR_HAVE_UNISTD_H 0 +#define APR_HAVE_STDDEF_H 1 +#define APR_HAVE_PROCESS_H 1 +#else +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 0 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 0 +#define APR_HAVE_DIRENT_H 0 +#define APR_HAVE_ERRNO_H 0 +#define APR_HAVE_FCNTL_H 0 +#define APR_HAVE_IO_H 0 +#define APR_HAVE_LIMITS_H 0 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#define APR_HAVE_NETINET_SCTP_H 0 +#define APR_HAVE_NETINET_SCTP_UIO_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SEMAPHORE_H 0 +#define APR_HAVE_SIGNAL_H 0 +#define APR_HAVE_STDARG_H 0 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_SYS_IOCTL_H 0 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SIGNAL_H 0 +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SOCKIO_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#define APR_HAVE_SYS_TYPES_H 0 +#define APR_HAVE_SYS_UIO_H 0 +#define APR_HAVE_SYS_UN_H 0 +#define APR_HAVE_SYS_WAIT_H 0 +#define APR_HAVE_TIME_H 0 +#define APR_HAVE_UNISTD_H 0 +#define APR_HAVE_STDDEF_H 0 +#define APR_HAVE_PROCESS_H 0 +#endif + +/** @} */ +/** @} */ + +/* We don't include our conditional headers within the doxyblocks + * or the extern "C" namespace + */ + +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_STDDEF_H +#include +#endif +#if APR_HAVE_TIME_H +#include +#endif +#if APR_HAVE_PROCESS_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup apr_platform + * @ingroup APR + * @{ + */ + +#define APR_HAVE_SHMEM_MMAP_TMP 0 +#define APR_HAVE_SHMEM_MMAP_SHM 0 +#define APR_HAVE_SHMEM_MMAP_ZERO 0 +#define APR_HAVE_SHMEM_SHMGET_ANON 0 +#define APR_HAVE_SHMEM_SHMGET 0 +#define APR_HAVE_SHMEM_MMAP_ANON 0 +#define APR_HAVE_SHMEM_BEOS 0 + +#define APR_USE_SHMEM_MMAP_TMP 0 +#define APR_USE_SHMEM_MMAP_SHM 0 +#define APR_USE_SHMEM_MMAP_ZERO 0 +#define APR_USE_SHMEM_SHMGET_ANON 0 +#define APR_USE_SHMEM_SHMGET 0 +#define APR_USE_SHMEM_MMAP_ANON 0 +#define APR_USE_SHMEM_BEOS 0 + +#define APR_USE_FLOCK_SERIALIZE 0 +#define APR_USE_POSIXSEM_SERIALIZE 0 +#define APR_USE_SYSVSEM_SERIALIZE 0 +#define APR_USE_FCNTL_SERIALIZE 0 +#define APR_USE_PROC_PTHREAD_SERIALIZE 0 +#define APR_USE_PTHREAD_SERIALIZE 0 + +#define APR_HAS_FLOCK_SERIALIZE 0 +#define APR_HAS_SYSVSEM_SERIALIZE 0 +#define APR_HAS_POSIXSEM_SERIALIZE 0 +#define APR_HAS_FCNTL_SERIALIZE 0 +#define APR_HAS_PROC_PTHREAD_SERIALIZE 0 + +#define APR_PROCESS_LOCK_IS_GLOBAL 0 + +#define APR_HAVE_CORKABLE_TCP 0 +#define APR_HAVE_GETRLIMIT 0 +#define APR_HAVE_ICONV 0 +#define APR_HAVE_IN_ADDR 1 +#define APR_HAVE_INET_ADDR 1 +#define APR_HAVE_INET_NETWORK 0 +#define APR_HAVE_IPV6 0 +#define APR_HAVE_MEMMOVE 1 +#define APR_HAVE_SETRLIMIT 0 +#define APR_HAVE_SIGACTION 0 +#define APR_HAVE_SIGSUSPEND 0 +#define APR_HAVE_SIGWAIT 0 +#define APR_HAVE_SA_STORAGE 0 +#define APR_HAVE_STRCASECMP 0 +#define APR_HAVE_STRDUP 1 +#define APR_HAVE_STRNCASECMP 0 +#define APR_HAVE_STRSTR 1 +#define APR_HAVE_MEMCHR 1 +#define APR_HAVE_STRUCT_RLIMIT 0 +#define APR_HAVE_UNION_SEMUN 0 +#define APR_HAVE_SCTP 0 +#define APR_HAVE_IOVEC 0 + +#ifndef _WIN32_WCE +#define APR_HAVE_STRICMP 1 +#define APR_HAVE_STRNICMP 1 +#else +#define APR_HAVE_STRICMP 0 +#define APR_HAVE_STRNICMP 0 +#endif + +/* APR Feature Macros */ +#define APR_HAS_SHARED_MEMORY 1 +#define APR_HAS_THREADS 1 +#define APR_HAS_MMAP 1 +#define APR_HAS_FORK 0 +#define APR_HAS_RANDOM 1 +#define APR_HAS_OTHER_CHILD 1 +#define APR_HAS_DSO 1 +#define APR_HAS_SO_ACCEPTFILTER 0 +#define APR_HAS_UNICODE_FS 1 +#define APR_HAS_PROC_INVOKED 1 +#define APR_HAS_OS_UUID 1 + +#ifndef _WIN32_WCE +#define APR_HAS_SENDFILE 1 +#define APR_HAS_USER 1 +#define APR_HAS_LARGE_FILES 1 +#define APR_HAS_XTHREAD_FILES 1 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 1 +#else +#define APR_HAS_SENDFILE 0 +#define APR_HAS_USER 0 +#define APR_HAS_LARGE_FILES 0 +#define APR_HAS_XTHREAD_FILES 0 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 +#endif + +/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible + * to poll on files/pipes. + */ +#define APR_FILES_AS_SOCKETS 0 + +/* This macro indicates whether or not EBCDIC is the native character set. + */ +#define APR_CHARSET_EBCDIC 0 + +/* If we have a TCP implementation that can be "corked", what flag + * do we use? + */ +#define APR_TCP_NOPUSH_FLAG @apr_tcp_nopush_flag@ + +/* Is the TCP_NODELAY socket option inherited from listening sockets? + */ +#define APR_TCP_NODELAY_INHERITED 1 + +/* Is the O_NONBLOCK flag inherited from listening sockets? + */ +#define APR_O_NONBLOCK_INHERITED 1 + +/* Typedefs that APR needs. */ + +typedef unsigned char apr_byte_t; + +typedef short apr_int16_t; +typedef unsigned short apr_uint16_t; + +typedef int apr_int32_t; +typedef unsigned int apr_uint32_t; + +typedef __int64 apr_int64_t; +typedef unsigned __int64 apr_uint64_t; + +typedef size_t apr_size_t; +#if APR_HAVE_STDDEF_H +typedef ptrdiff_t apr_ssize_t; +#else +typedef int apr_ssize_t; +#endif +#if APR_HAS_LARGE_FILES +typedef __int64 apr_off_t; +#else +typedef int apr_off_t; +#endif +typedef int apr_socklen_t; +typedef apr_uint64_t apr_ino_t; + +#ifdef _WIN64 +#define APR_SIZEOF_VOIDP 8 +#else +#define APR_SIZEOF_VOIDP 4 +#endif + +#if APR_SIZEOF_VOIDP == 8 +typedef apr_uint64_t apr_uintptr_t; +#else +typedef apr_uint32_t apr_uintptr_t; +#endif + +/* Are we big endian? */ +/* XXX: Fatal assumption on Alpha platforms */ +#define APR_IS_BIGENDIAN 0 + +/* Mechanisms to properly type numeric literals */ + +#ifndef __GNUC__ +#define APR_INT64_C(val) (val##i64) +#define APR_UINT64_C(val) (val##Ui64) +#else +#define APR_INT64_C(val) (val##LL) +#define APR_UINT64_C(val) (val##ULL) +#endif + +#ifdef INT16_MIN +#define APR_INT16_MIN INT16_MIN +#else +#define APR_INT16_MIN (-0x7fff - 1) +#endif + +#ifdef INT16_MAX +#define APR_INT16_MAX INT16_MAX +#else +#define APR_INT16_MAX (0x7fff) +#endif + +#ifdef UINT16_MAX +#define APR_UINT16_MAX UINT16_MAX +#else +#define APR_UINT16_MAX (0xffff) +#endif + +#ifdef INT32_MIN +#define APR_INT32_MIN INT32_MIN +#else +#define APR_INT32_MIN (-0x7fffffff - 1) +#endif + +#ifdef INT32_MAX +#define APR_INT32_MAX INT32_MAX +#else +#define APR_INT32_MAX 0x7fffffff +#endif + +#ifdef UINT32_MAX +#define APR_UINT32_MAX UINT32_MAX +#else +#define APR_UINT32_MAX (0xffffffffU) +#endif + +#ifdef INT64_MIN +#define APR_INT64_MIN INT64_MIN +#else +#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1) +#endif + +#ifdef INT64_MAX +#define APR_INT64_MAX INT64_MAX +#else +#define APR_INT64_MAX APR_INT64_C(0x7fffffffffffffff) +#endif + +#ifdef UINT64_MAX +#define APR_UINT64_MAX UINT64_MAX +#else +#define APR_UINT64_MAX APR_UINT64_C(0xffffffffffffffff) +#endif + +#define APR_SIZE_MAX (~((apr_size_t)0)) + +/* Definitions that APR programs need to work properly. */ + +/** + * APR public API wrap for C++ compilers. + */ +#ifdef __cplusplus +#define APR_BEGIN_DECLS extern "C" { +#define APR_END_DECLS } +#else +#define APR_BEGIN_DECLS +#define APR_END_DECLS +#endif + +/** + * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC, + * so that they follow the platform's calling convention. + *
+ *
+ * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
+ *
+ * 
+ */ +#define APR_THREAD_FUNC __stdcall + + +#if defined(DOXYGEN) || !defined(WIN32) + +/** + * The public APR functions are declared with APR_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APR_DECLARE_NONSTD(). + * + * @remark Both the declaration and implementations must use the same macro. + * + *
+ * APR_DECLARE(rettype) apr_func(args)
+ * 
+ * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA + * @remark Note that when APR compiles the library itself, it passes the + * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32) + * to export public symbols from the dynamic library build.\n + * The user must define the APR_DECLARE_STATIC when compiling to target + * the static APR library on some platforms (e.g. Win32.) The public symbols + * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n + * By default, compiling an application and including the APR public + * headers, without defining APR_DECLARE_STATIC, will prepare the code to be + * linked to the dynamic library. + */ +#define APR_DECLARE(type) type + +/** + * The public APR functions using variable arguments are declared with + * APR_DECLARE_NONSTD(), as they must follow the C language calling convention. + * @see APR_DECLARE @see APR_DECLARE_DATA + * @remark Both the declaration and implementations must use the same macro. + *
+ *
+ * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ *
+ * 
+ */ +#define APR_DECLARE_NONSTD(type) type + +/** + * The public APR variables are declared with AP_MODULE_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * @see APR_DECLARE @see APR_DECLARE_NONSTD + * @remark Note that the declaration and implementations use different forms, + * but both must include the macro. + * + *
+ *
+ * extern APR_DECLARE_DATA type apr_variable;\n
+ * APR_DECLARE_DATA type apr_variable = value;
+ *
+ * 
+ */ +#define APR_DECLARE_DATA + +#elif defined(APR_DECLARE_STATIC) +#define APR_DECLARE(type) type __stdcall +#define APR_DECLARE_NONSTD(type) type __cdecl +#define APR_DECLARE_DATA +#elif defined(APR_DECLARE_EXPORT) +#define APR_DECLARE(type) __declspec(dllexport) type __stdcall +#define APR_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define APR_DECLARE_DATA __declspec(dllexport) +#else +#define APR_DECLARE(type) __declspec(dllimport) type __stdcall +#define APR_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define APR_DECLARE_DATA __declspec(dllimport) +#endif + +#ifdef _WIN64 +#define APR_SSIZE_T_FMT "I64d" +#define APR_SIZE_T_FMT "I64u" +#else +#define APR_SSIZE_T_FMT "d" +#define APR_SIZE_T_FMT "u" +#endif + +#if APR_HAS_LARGE_FILES +#define APR_OFF_T_FMT "I64d" +#else +#define APR_OFF_T_FMT "d" +#endif + +#define APR_PID_T_FMT "d" + +#define APR_INT64_T_FMT "I64d" +#define APR_UINT64_T_FMT "I64u" +#define APR_UINT64_T_HEX_FMT "I64x" + +/* No difference between PROC and GLOBAL mutex */ +#define APR_PROC_MUTEX_IS_GLOBAL 1 + +/* Local machine definition for console and log output. */ +#define APR_EOL_STR "\r\n" + +typedef int apr_wait_t; + +#if APR_HAS_UNICODE_FS +/* An arbitrary size that is digestable. True max is a bit less than 32000 */ +#define APR_PATH_MAX 8192 +#else /* !APR_HAS_UNICODE_FS */ +#define APR_PATH_MAX MAX_PATH +#endif + +#define APR_DSOPATH "PATH" + +/** @} */ + +/* Definitions that only Win32 programs need to compile properly. */ + +/* XXX These simply don't belong here, perhaps in apr_portable.h + * based on some APR_HAVE_PID/GID/UID? + */ +#ifndef __GNUC__ +typedef int pid_t; +#endif +typedef int uid_t; +typedef int gid_t; + +/* Win32 .h ommissions we really need */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#if APR_HAVE_IPV6 + +/* Appears in later flavors, not the originals. */ +#ifndef in_addr6 +#define in6_addr in_addr6 +#endif + +#ifndef WS2TCPIP_INLINE +#define IN6_IS_ADDR_V4MAPPED(a) \ + ( (*(const apr_uint64_t *)(const void *)(&(a)->s6_addr[0]) == 0) \ + && (*(const apr_uint32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff))) +#endif + +#endif /* APR_HAS_IPV6 */ + +#ifdef __cplusplus +} +#endif + +/* Done with badly written headers + */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#pragma warning(pop) +#pragma warning(disable: 4996) +#endif + +#endif /* WIN32 */ + +#endif /* APR_H */ diff --git a/code/application/source/sf_app/code/include/apr_errno.h b/code/application/source/sf_app/code/include/apr_errno.h new file mode 100755 index 000000000..b60822b24 --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_errno.h @@ -0,0 +1,1316 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_ERRNO_H +#define APR_ERRNO_H + +/** + * @file apr_errno.h + * @brief APR Error Codes + */ + +#include "apr.h" + +#if APR_HAVE_ERRNO_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_errno Error Codes + * @ingroup APR + * @{ + */ + +/** + * Type for specifying an error or status code. + */ +typedef int apr_status_t; + +/** + * Return a human readable string describing the specified error. + * @param statcode The error code to get a string for. + * @param buf A buffer to hold the error string. + * @param bufsize Size of the buffer to hold the string. + */ +/*APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, + apr_size_t bufsize);*/ + +#if 0 +defined(DOXYGEN) +/** + * @def APR_FROM_OS_ERROR(os_err_type syserr) + * Fold a platform specific error into an apr_status_t code. + * @return apr_status_t + * @param e The platform os error code. + * @warning macro implementation; the syserr argument may be evaluated + * multiple times. + */ +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) + +/** + * @def APR_TO_OS_ERROR(apr_status_t statcode) + * @return os_err_type + * Fold an apr_status_t code back to the native platform defined error. + * @param e The apr_status_t folded platform os error code. + * @warning macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. + */ +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +/** @def apr_get_os_error() + * @return apr_status_t the last platform error, folded into apr_status_t, on most platforms + * @remark This retrieves errno, or calls a GetLastError() style function, and + * folds it with APR_FROM_OS_ERROR. Some platforms (such as OS2) have no + * such mechanism, so this call may be unsupported. Do NOT use this + * call for socket errors from socket, send, recv etc! + */ + +/** @def apr_set_os_error(e) + * Reset the last platform error, unfolded from an apr_status_t, on some platforms + * @param e The OS error folded in a prior call to APR_FROM_OS_ERROR() + * @warning This is a macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. This macro sets + * errno, or calls a SetLastError() style function, unfolding statcode + * with APR_TO_OS_ERROR. Some platforms (such as OS2) have no such + * mechanism, so this call may be unsupported. + */ + +/** @def apr_get_netos_error() + * Return the last socket error, folded into apr_status_t, on all platforms + * @remark This retrieves errno or calls a GetLastSocketError() style function, + * and folds it with APR_FROM_OS_ERROR. + */ + +/** @def apr_set_netos_error(e) + * Reset the last socket error, unfolded from an apr_status_t + * @param e The socket error folded in a prior call to APR_FROM_OS_ERROR() + * @warning This is a macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. This macro sets + * errno, or calls a WSASetLastError() style function, unfolding + * socketcode with APR_TO_OS_ERROR. + */ + +#endif /* defined(DOXYGEN) */ + +/** + * APR_OS_START_ERROR is where the APR specific error values start. + */ +#define APR_OS_START_ERROR 20000 +/** + * APR_OS_ERRSPACE_SIZE is the maximum number of errors you can fit + * into one of the error/status ranges below -- except for + * APR_OS_START_USERERR, which see. + */ +#define APR_OS_ERRSPACE_SIZE 50000 +/** + * APR_UTIL_ERRSPACE_SIZE is the size of the space that is reserved for + * use within apr-util. This space is reserved above that used by APR + * internally. + * @note This number MUST be smaller than APR_OS_ERRSPACE_SIZE by a + * large enough amount that APR has sufficient room for its + * codes. + */ +#define APR_UTIL_ERRSPACE_SIZE 20000 +/** + * APR_OS_START_STATUS is where the APR specific status codes start. + */ +#define APR_OS_START_STATUS (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE) +/** + * APR_UTIL_START_STATUS is where APR-Util starts defining its + * status codes. + */ +#define APR_UTIL_START_STATUS (APR_OS_START_STATUS + \ + (APR_OS_ERRSPACE_SIZE - APR_UTIL_ERRSPACE_SIZE)) +/** + * APR_OS_START_USERERR are reserved for applications that use APR that + * layer their own error codes along with APR's. Note that the + * error immediately following this one is set ten times farther + * away than usual, so that users of apr have a lot of room in + * which to declare custom error codes. + * + * In general applications should try and create unique error codes. To try + * and assist in finding suitable ranges of numbers to use, the following + * ranges are known to be used by the listed applications. If your + * application defines error codes please advise the range of numbers it + * uses to dev@apr.apache.org for inclusion in this list. + * + * Ranges shown are in relation to APR_OS_START_USERERR + * + * Subversion - Defined ranges, of less than 100, at intervals of 5000 + * starting at an offset of 5000, e.g. + * +5000 to 5100, +10000 to 10100 + * + * Apache HTTPD - +2000 to 2999 + */ +#define APR_OS_START_USERERR (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_USEERR is obsolete, defined for compatibility only. + * Use APR_OS_START_USERERR instead. + */ +#define APR_OS_START_USEERR APR_OS_START_USERERR +/** + * APR_OS_START_CANONERR is where APR versions of errno values are defined + * on systems which don't have the corresponding errno. + */ +#define APR_OS_START_CANONERR (APR_OS_START_USERERR \ + + (APR_OS_ERRSPACE_SIZE * 10)) +/** + * APR_OS_START_EAIERR folds EAI_ error codes from getaddrinfo() into + * apr_status_t values. + */ +#define APR_OS_START_EAIERR (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_SYSERR folds platform-specific system error values into + * apr_status_t values. + */ +#define APR_OS_START_SYSERR (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE) + +/** + * @defgroup APR_ERROR_map APR Error Space + *
+ * The following attempts to show the relation of the various constants
+ * used for mapping APR Status codes.
+ *
+ *       0
+ *
+ *  20,000     APR_OS_START_ERROR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ *  70,000      APR_OS_START_STATUS
+ *
+ *         + APR_OS_ERRSPACE_SIZE - APR_UTIL_ERRSPACE_SIZE (30,000)
+ *
+ * 100,000      APR_UTIL_START_STATUS
+ *
+ *         + APR_UTIL_ERRSPACE_SIZE (20,000)
+ *
+ * 120,000      APR_OS_START_USERERR
+ *
+ *         + 10 x APR_OS_ERRSPACE_SIZE (50,000 * 10)
+ *
+ * 620,000      APR_OS_START_CANONERR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ * 670,000      APR_OS_START_EAIERR
+ *
+ *         + APR_OS_ERRSPACE_SIZE (50,000)
+ *
+ * 720,000      APR_OS_START_SYSERR
+ *
+ * 
+ */ + +/** no error. */ +#define APR_SUCCESS 0 + +/** + * @defgroup APR_Error APR Error Values + *
+ * APR ERROR VALUES
+ * APR_ENOSTAT      APR was unable to perform a stat on the file
+ * APR_ENOPOOL      APR was not provided a pool with which to allocate memory
+ * APR_EBADDATE     APR was given an invalid date
+ * APR_EINVALSOCK   APR was given an invalid socket
+ * APR_ENOPROC      APR was not given a process structure
+ * APR_ENOTIME      APR was not given a time structure
+ * APR_ENODIR       APR was not given a directory structure
+ * APR_ENOLOCK      APR was not given a lock structure
+ * APR_ENOPOLL      APR was not given a poll structure
+ * APR_ENOSOCKET    APR was not given a socket
+ * APR_ENOTHREAD    APR was not given a thread structure
+ * APR_ENOTHDKEY    APR was not given a thread key structure
+ * APR_ENOSHMAVAIL  There is no more shared memory available
+ * APR_EDSOOPEN     APR was unable to open the dso object.  For more
+ *                  information call apr_dso_error().
+ * APR_EGENERAL     General failure (specific information not available)
+ * APR_EBADIP       The specified IP address is invalid
+ * APR_EBADMASK     The specified netmask is invalid
+ * APR_ESYMNOTFOUND Could not find the requested symbol
+ * APR_ENOTENOUGHENTROPY Not enough entropy to continue
+ * 
+ * + *
+ * APR STATUS VALUES
+ * APR_INCHILD        Program is currently executing in the child
+ * APR_INPARENT       Program is currently executing in the parent
+ * APR_DETACH         The thread is detached
+ * APR_NOTDETACH      The thread is not detached
+ * APR_CHILD_DONE     The child has finished executing
+ * APR_CHILD_NOTDONE  The child has not finished executing
+ * APR_TIMEUP         The operation did not finish before the timeout
+ * APR_INCOMPLETE     The operation was incomplete although some processing
+ *                    was performed and the results are partially valid
+ * APR_BADCH          Getopt found an option not in the option string
+ * APR_BADARG         Getopt found an option that is missing an argument
+ *                    and an argument was specified in the option string
+ * APR_EOF            APR has encountered the end of the file
+ * APR_NOTFOUND       APR was unable to find the socket in the poll structure
+ * APR_ANONYMOUS      APR is using anonymous shared memory
+ * APR_FILEBASED      APR is using a file name as the key to the shared memory
+ * APR_KEYBASED       APR is using a shared key as the key to the shared memory
+ * APR_EINIT          Ininitalizer value.  If no option has been found, but
+ *                    the status variable requires a value, this should be used
+ * APR_ENOTIMPL       The APR function has not been implemented on this
+ *                    platform, either because nobody has gotten to it yet,
+ *                    or the function is impossible on this platform.
+ * APR_EMISMATCH      Two passwords do not match.
+ * APR_EABSOLUTE      The given path was absolute.
+ * APR_ERELATIVE      The given path was relative.
+ * APR_EINCOMPLETE    The given path was neither relative nor absolute.
+ * APR_EABOVEROOT     The given path was above the root path.
+ * APR_EBUSY          The given lock was busy.
+ * APR_EPROC_UNKNOWN  The given process wasn't recognized by APR
+ * 
+ * @{ + */ +/** @see APR_STATUS_IS_ENOSTAT */ +#define APR_ENOSTAT (APR_OS_START_ERROR + 1) +/** @see APR_STATUS_IS_ENOPOOL */ +#define APR_ENOPOOL (APR_OS_START_ERROR + 2) +/* empty slot: +3 */ +/** @see APR_STATUS_IS_EBADDATE */ +#define APR_EBADDATE (APR_OS_START_ERROR + 4) +/** @see APR_STATUS_IS_EINVALSOCK */ +#define APR_EINVALSOCK (APR_OS_START_ERROR + 5) +/** @see APR_STATUS_IS_ENOPROC */ +#define APR_ENOPROC (APR_OS_START_ERROR + 6) +/** @see APR_STATUS_IS_ENOTIME */ +#define APR_ENOTIME (APR_OS_START_ERROR + 7) +/** @see APR_STATUS_IS_ENODIR */ +#define APR_ENODIR (APR_OS_START_ERROR + 8) +/** @see APR_STATUS_IS_ENOLOCK */ +#define APR_ENOLOCK (APR_OS_START_ERROR + 9) +/** @see APR_STATUS_IS_ENOPOLL */ +#define APR_ENOPOLL (APR_OS_START_ERROR + 10) +/** @see APR_STATUS_IS_ENOSOCKET */ +#define APR_ENOSOCKET (APR_OS_START_ERROR + 11) +/** @see APR_STATUS_IS_ENOTHREAD */ +#define APR_ENOTHREAD (APR_OS_START_ERROR + 12) +/** @see APR_STATUS_IS_ENOTHDKEY */ +#define APR_ENOTHDKEY (APR_OS_START_ERROR + 13) +/** @see APR_STATUS_IS_EGENERAL */ +#define APR_EGENERAL (APR_OS_START_ERROR + 14) +/** @see APR_STATUS_IS_ENOSHMAVAIL */ +#define APR_ENOSHMAVAIL (APR_OS_START_ERROR + 15) +/** @see APR_STATUS_IS_EBADIP */ +#define APR_EBADIP (APR_OS_START_ERROR + 16) +/** @see APR_STATUS_IS_EBADMASK */ +#define APR_EBADMASK (APR_OS_START_ERROR + 17) +/* empty slot: +18 */ +/** @see APR_STATUS_IS_EDSOPEN */ +#define APR_EDSOOPEN (APR_OS_START_ERROR + 19) +/** @see APR_STATUS_IS_EABSOLUTE */ +#define APR_EABSOLUTE (APR_OS_START_ERROR + 20) +/** @see APR_STATUS_IS_ERELATIVE */ +#define APR_ERELATIVE (APR_OS_START_ERROR + 21) +/** @see APR_STATUS_IS_EINCOMPLETE */ +#define APR_EINCOMPLETE (APR_OS_START_ERROR + 22) +/** @see APR_STATUS_IS_EABOVEROOT */ +#define APR_EABOVEROOT (APR_OS_START_ERROR + 23) +/** @see APR_STATUS_IS_EBADPATH */ +#define APR_EBADPATH (APR_OS_START_ERROR + 24) +/** @see APR_STATUS_IS_EPATHWILD */ +#define APR_EPATHWILD (APR_OS_START_ERROR + 25) +/** @see APR_STATUS_IS_ESYMNOTFOUND */ +#define APR_ESYMNOTFOUND (APR_OS_START_ERROR + 26) +/** @see APR_STATUS_IS_EPROC_UNKNOWN */ +#define APR_EPROC_UNKNOWN (APR_OS_START_ERROR + 27) +/** @see APR_STATUS_IS_ENOTENOUGHENTROPY */ +#define APR_ENOTENOUGHENTROPY (APR_OS_START_ERROR + 28) +/** @} */ + +/** + * @defgroup APR_STATUS_IS Status Value Tests + * @warning For any particular error condition, more than one of these tests + * may match. This is because platform-specific error codes may not + * always match the semantics of the POSIX codes these tests (and the + * corresponding APR error codes) are named after. A notable example + * are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on + * Win32 platforms. The programmer should always be aware of this and + * adjust the order of the tests accordingly. + * @{ + */ +/** + * APR was unable to perform a stat on the file + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOSTAT(s) ((s) == APR_ENOSTAT) +/** + * APR was not provided a pool with which to allocate memory + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOPOOL(s) ((s) == APR_ENOPOOL) +/** APR was given an invalid date */ +#define APR_STATUS_IS_EBADDATE(s) ((s) == APR_EBADDATE) +/** APR was given an invalid socket */ +#define APR_STATUS_IS_EINVALSOCK(s) ((s) == APR_EINVALSOCK) +/** APR was not given a process structure */ +#define APR_STATUS_IS_ENOPROC(s) ((s) == APR_ENOPROC) +/** APR was not given a time structure */ +#define APR_STATUS_IS_ENOTIME(s) ((s) == APR_ENOTIME) +/** APR was not given a directory structure */ +#define APR_STATUS_IS_ENODIR(s) ((s) == APR_ENODIR) +/** APR was not given a lock structure */ +#define APR_STATUS_IS_ENOLOCK(s) ((s) == APR_ENOLOCK) +/** APR was not given a poll structure */ +#define APR_STATUS_IS_ENOPOLL(s) ((s) == APR_ENOPOLL) +/** APR was not given a socket */ +#define APR_STATUS_IS_ENOSOCKET(s) ((s) == APR_ENOSOCKET) +/** APR was not given a thread structure */ +#define APR_STATUS_IS_ENOTHREAD(s) ((s) == APR_ENOTHREAD) +/** APR was not given a thread key structure */ +#define APR_STATUS_IS_ENOTHDKEY(s) ((s) == APR_ENOTHDKEY) +/** Generic Error which can not be put into another spot */ +#define APR_STATUS_IS_EGENERAL(s) ((s) == APR_EGENERAL) +/** There is no more shared memory available */ +#define APR_STATUS_IS_ENOSHMAVAIL(s) ((s) == APR_ENOSHMAVAIL) +/** The specified IP address is invalid */ +#define APR_STATUS_IS_EBADIP(s) ((s) == APR_EBADIP) +/** The specified netmask is invalid */ +#define APR_STATUS_IS_EBADMASK(s) ((s) == APR_EBADMASK) +/* empty slot: +18 */ +/** + * APR was unable to open the dso object. + * For more information call apr_dso_error(). + */ +#if defined(WIN32) +#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN \ + || APR_TO_OS_ERROR(s) == ERROR_MOD_NOT_FOUND) +#else +#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN) +#endif +/** The given path was absolute. */ +#define APR_STATUS_IS_EABSOLUTE(s) ((s) == APR_EABSOLUTE) +/** The given path was relative. */ +#define APR_STATUS_IS_ERELATIVE(s) ((s) == APR_ERELATIVE) +/** The given path was neither relative nor absolute. */ +#define APR_STATUS_IS_EINCOMPLETE(s) ((s) == APR_EINCOMPLETE) +/** The given path was above the root path. */ +#define APR_STATUS_IS_EABOVEROOT(s) ((s) == APR_EABOVEROOT) +/** The given path was bad. */ +#define APR_STATUS_IS_EBADPATH(s) ((s) == APR_EBADPATH) +/** The given path contained wildcards. */ +#define APR_STATUS_IS_EPATHWILD(s) ((s) == APR_EPATHWILD) +/** Could not find the requested symbol. + * For more information call apr_dso_error(). + */ +#if defined(WIN32) +#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND \ + || APR_TO_OS_ERROR(s) == ERROR_PROC_NOT_FOUND) +#else +#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND) +#endif +/** The given process was not recognized by APR. */ +#define APR_STATUS_IS_EPROC_UNKNOWN(s) ((s) == APR_EPROC_UNKNOWN) +/** APR could not gather enough entropy to continue. */ +#define APR_STATUS_IS_ENOTENOUGHENTROPY(s) ((s) == APR_ENOTENOUGHENTROPY) + +/** @} */ + +/** + * @addtogroup APR_Error + * @{ + */ +/** @see APR_STATUS_IS_INCHILD */ +#define APR_INCHILD (APR_OS_START_STATUS + 1) +/** @see APR_STATUS_IS_INPARENT */ +#define APR_INPARENT (APR_OS_START_STATUS + 2) +/** @see APR_STATUS_IS_DETACH */ +#define APR_DETACH (APR_OS_START_STATUS + 3) +/** @see APR_STATUS_IS_NOTDETACH */ +#define APR_NOTDETACH (APR_OS_START_STATUS + 4) +/** @see APR_STATUS_IS_CHILD_DONE */ +#define APR_CHILD_DONE (APR_OS_START_STATUS + 5) +/** @see APR_STATUS_IS_CHILD_NOTDONE */ +#define APR_CHILD_NOTDONE (APR_OS_START_STATUS + 6) +/** @see APR_STATUS_IS_TIMEUP */ +#define APR_TIMEUP (APR_OS_START_STATUS + 7) +/** @see APR_STATUS_IS_INCOMPLETE */ +#define APR_INCOMPLETE (APR_OS_START_STATUS + 8) +/* empty slot: +9 */ +/* empty slot: +10 */ +/* empty slot: +11 */ +/** @see APR_STATUS_IS_BADCH */ +#define APR_BADCH (APR_OS_START_STATUS + 12) +/** @see APR_STATUS_IS_BADARG */ +#define APR_BADARG (APR_OS_START_STATUS + 13) +/** @see APR_STATUS_IS_EOF */ +#define APR_EOF (APR_OS_START_STATUS + 14) +/** @see APR_STATUS_IS_NOTFOUND */ +#define APR_NOTFOUND (APR_OS_START_STATUS + 15) +/* empty slot: +16 */ +/* empty slot: +17 */ +/* empty slot: +18 */ +/** @see APR_STATUS_IS_ANONYMOUS */ +#define APR_ANONYMOUS (APR_OS_START_STATUS + 19) +/** @see APR_STATUS_IS_FILEBASED */ +#define APR_FILEBASED (APR_OS_START_STATUS + 20) +/** @see APR_STATUS_IS_KEYBASED */ +#define APR_KEYBASED (APR_OS_START_STATUS + 21) +/** @see APR_STATUS_IS_EINIT */ +#define APR_EINIT (APR_OS_START_STATUS + 22) +/** @see APR_STATUS_IS_ENOTIMPL */ +#define APR_ENOTIMPL (APR_OS_START_STATUS + 23) +/** @see APR_STATUS_IS_EMISMATCH */ +#define APR_EMISMATCH (APR_OS_START_STATUS + 24) +/** @see APR_STATUS_IS_EBUSY */ +#define APR_EBUSY (APR_OS_START_STATUS + 25) +/** @} */ + +/** + * @addtogroup APR_STATUS_IS + * @{ + */ +/** + * Program is currently executing in the child + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code */ +#define APR_STATUS_IS_INCHILD(s) ((s) == APR_INCHILD) +/** + * Program is currently executing in the parent + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_INPARENT(s) ((s) == APR_INPARENT) +/** + * The thread is detached + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_DETACH(s) ((s) == APR_DETACH) +/** + * The thread is not detached + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_NOTDETACH(s) ((s) == APR_NOTDETACH) +/** + * The child has finished executing + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_CHILD_DONE(s) ((s) == APR_CHILD_DONE) +/** + * The child has not finished executing + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_CHILD_NOTDONE(s) ((s) == APR_CHILD_NOTDONE) +/** + * The operation did not finish before the timeout + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP) +/** + * The operation was incomplete although some processing was performed + * and the results are partially valid. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_INCOMPLETE(s) ((s) == APR_INCOMPLETE) +/* empty slot: +9 */ +/* empty slot: +10 */ +/* empty slot: +11 */ +/** + * Getopt found an option not in the option string + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_BADCH(s) ((s) == APR_BADCH) +/** + * Getopt found an option not in the option string and an argument was + * specified in the option string + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_BADARG(s) ((s) == APR_BADARG) +/** + * APR has encountered the end of the file + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EOF(s) ((s) == APR_EOF) +/** + * APR was unable to find the socket in the poll structure + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_NOTFOUND(s) ((s) == APR_NOTFOUND) +/* empty slot: +16 */ +/* empty slot: +17 */ +/* empty slot: +18 */ +/** + * APR is using anonymous shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ANONYMOUS(s) ((s) == APR_ANONYMOUS) +/** + * APR is using a file name as the key to the shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_FILEBASED(s) ((s) == APR_FILEBASED) +/** + * APR is using a shared key as the key to the shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_KEYBASED(s) ((s) == APR_KEYBASED) +/** + * Ininitalizer value. If no option has been found, but + * the status variable requires a value, this should be used + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EINIT(s) ((s) == APR_EINIT) +/** + * The APR function has not been implemented on this + * platform, either because nobody has gotten to it yet, + * or the function is impossible on this platform. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOTIMPL(s) ((s) == APR_ENOTIMPL) +/** + * Two passwords do not match. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EMISMATCH(s) ((s) == APR_EMISMATCH) +/** + * The given lock was busy + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EBUSY(s) ((s) == APR_EBUSY) + +/** @} */ + +/** + * @addtogroup APR_Error APR Error Values + * @{ + */ +/* APR CANONICAL ERROR VALUES */ +/** @see APR_STATUS_IS_EACCES */ +#ifdef EACCES +#define APR_EACCES EACCES +#else +#define APR_EACCES (APR_OS_START_CANONERR + 1) +#endif + +/** @see APR_STATUS_IS_EEXIST */ +#ifdef EEXIST +#define APR_EEXIST EEXIST +#else +#define APR_EEXIST (APR_OS_START_CANONERR + 2) +#endif + +/** @see APR_STATUS_IS_ENAMETOOLONG */ +#ifdef ENAMETOOLONG +#define APR_ENAMETOOLONG ENAMETOOLONG +#else +#define APR_ENAMETOOLONG (APR_OS_START_CANONERR + 3) +#endif + +/** @see APR_STATUS_IS_ENOENT */ +#ifdef ENOENT +#define APR_ENOENT ENOENT +#else +#define APR_ENOENT (APR_OS_START_CANONERR + 4) +#endif + +/** @see APR_STATUS_IS_ENOTDIR */ +#ifdef ENOTDIR +#define APR_ENOTDIR ENOTDIR +#else +#define APR_ENOTDIR (APR_OS_START_CANONERR + 5) +#endif + +/** @see APR_STATUS_IS_ENOSPC */ +#ifdef ENOSPC +#define APR_ENOSPC ENOSPC +#else +#define APR_ENOSPC (APR_OS_START_CANONERR + 6) +#endif + +/** @see APR_STATUS_IS_ENOMEM */ +#ifdef ENOMEM +#define APR_ENOMEM ENOMEM +#else +#define APR_ENOMEM (APR_OS_START_CANONERR + 7) +#endif + +/** @see APR_STATUS_IS_EMFILE */ +#ifdef EMFILE +#define APR_EMFILE EMFILE +#else +#define APR_EMFILE (APR_OS_START_CANONERR + 8) +#endif + +/** @see APR_STATUS_IS_ENFILE */ +#ifdef ENFILE +#define APR_ENFILE ENFILE +#else +#define APR_ENFILE (APR_OS_START_CANONERR + 9) +#endif + +/** @see APR_STATUS_IS_EBADF */ +#ifdef EBADF +#define APR_EBADF EBADF +#else +#define APR_EBADF (APR_OS_START_CANONERR + 10) +#endif + +/** @see APR_STATUS_IS_EINVAL */ +#ifdef EINVAL +#define APR_EINVAL EINVAL +#else +#define APR_EINVAL (APR_OS_START_CANONERR + 11) +#endif + +/** @see APR_STATUS_IS_ESPIPE */ +#ifdef ESPIPE +#define APR_ESPIPE ESPIPE +#else +#define APR_ESPIPE (APR_OS_START_CANONERR + 12) +#endif + +/** + * @see APR_STATUS_IS_EAGAIN + * @warning use APR_STATUS_IS_EAGAIN instead of just testing this value + */ +#ifdef EAGAIN +#define APR_EAGAIN EAGAIN +#elif defined(EWOULDBLOCK) +#define APR_EAGAIN EWOULDBLOCK +#else +#define APR_EAGAIN (APR_OS_START_CANONERR + 13) +#endif + +/** @see APR_STATUS_IS_EINTR */ +#ifdef EINTR +#define APR_EINTR EINTR +#else +#define APR_EINTR (APR_OS_START_CANONERR + 14) +#endif + +/** @see APR_STATUS_IS_ENOTSOCK */ +#ifdef ENOTSOCK +#define APR_ENOTSOCK ENOTSOCK +#else +#define APR_ENOTSOCK (APR_OS_START_CANONERR + 15) +#endif + +/** @see APR_STATUS_IS_ECONNREFUSED */ +#ifdef ECONNREFUSED +#define APR_ECONNREFUSED ECONNREFUSED +#else +#define APR_ECONNREFUSED (APR_OS_START_CANONERR + 16) +#endif + +/** @see APR_STATUS_IS_EINPROGRESS */ +#ifdef EINPROGRESS +#define APR_EINPROGRESS EINPROGRESS +#else +#define APR_EINPROGRESS (APR_OS_START_CANONERR + 17) +#endif + +/** + * @see APR_STATUS_IS_ECONNABORTED + * @warning use APR_STATUS_IS_ECONNABORTED instead of just testing this value + */ + +#ifdef ECONNABORTED +#define APR_ECONNABORTED ECONNABORTED +#else +#define APR_ECONNABORTED (APR_OS_START_CANONERR + 18) +#endif + +/** @see APR_STATUS_IS_ECONNRESET */ +#ifdef ECONNRESET +#define APR_ECONNRESET ECONNRESET +#else +#define APR_ECONNRESET (APR_OS_START_CANONERR + 19) +#endif + +/** @see APR_STATUS_IS_ETIMEDOUT + * @deprecated */ +#ifdef ETIMEDOUT +#define APR_ETIMEDOUT ETIMEDOUT +#else +#define APR_ETIMEDOUT (APR_OS_START_CANONERR + 20) +#endif + +/** @see APR_STATUS_IS_EHOSTUNREACH */ +#ifdef EHOSTUNREACH +#define APR_EHOSTUNREACH EHOSTUNREACH +#else +#define APR_EHOSTUNREACH (APR_OS_START_CANONERR + 21) +#endif + +/** @see APR_STATUS_IS_ENETUNREACH */ +#ifdef ENETUNREACH +#define APR_ENETUNREACH ENETUNREACH +#else +#define APR_ENETUNREACH (APR_OS_START_CANONERR + 22) +#endif + +/** @see APR_STATUS_IS_EFTYPE */ +#ifdef EFTYPE +#define APR_EFTYPE EFTYPE +#else +#define APR_EFTYPE (APR_OS_START_CANONERR + 23) +#endif + +/** @see APR_STATUS_IS_EPIPE */ +#ifdef EPIPE +#define APR_EPIPE EPIPE +#else +#define APR_EPIPE (APR_OS_START_CANONERR + 24) +#endif + +/** @see APR_STATUS_IS_EXDEV */ +#ifdef EXDEV +#define APR_EXDEV EXDEV +#else +#define APR_EXDEV (APR_OS_START_CANONERR + 25) +#endif + +/** @see APR_STATUS_IS_ENOTEMPTY */ +#ifdef ENOTEMPTY +#define APR_ENOTEMPTY ENOTEMPTY +#else +#define APR_ENOTEMPTY (APR_OS_START_CANONERR + 26) +#endif + +/** @see APR_STATUS_IS_EAFNOSUPPORT */ +#ifdef EAFNOSUPPORT +#define APR_EAFNOSUPPORT EAFNOSUPPORT +#else +#define APR_EAFNOSUPPORT (APR_OS_START_CANONERR + 27) +#endif + +/** @} */ + +#if defined(OS2) && !defined(DOXYGEN) + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define INCL_DOSERRORS +#define INCL_DOS + +/* Leave these undefined. + * OS2 doesn't rely on the errno concept. + * The API calls always return a result codes which + * should be filtered through APR_FROM_OS_ERROR(). + * + * #define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) + * #define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) + */ + +/* A special case, only socket calls require this; + */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(errno)) +#define apr_set_netos_error(e) (errno = APR_TO_OS_ERROR(e)) + +/* And this needs to be greped away for good: + */ +#define APR_OS2_STATUS(e) (APR_FROM_OS_ERROR(e)) + +/* These can't sit in a private header, so in spite of the extra size, + * they need to be made available here. + */ +#define SOCBASEERR 10000 +#define SOCEPERM (SOCBASEERR+1) /* Not owner */ +#define SOCESRCH (SOCBASEERR+3) /* No such process */ +#define SOCEINTR (SOCBASEERR+4) /* Interrupted system call */ +#define SOCENXIO (SOCBASEERR+6) /* No such device or address */ +#define SOCEBADF (SOCBASEERR+9) /* Bad file number */ +#define SOCEACCES (SOCBASEERR+13) /* Permission denied */ +#define SOCEFAULT (SOCBASEERR+14) /* Bad address */ +#define SOCEINVAL (SOCBASEERR+22) /* Invalid argument */ +#define SOCEMFILE (SOCBASEERR+24) /* Too many open files */ +#define SOCEPIPE (SOCBASEERR+32) /* Broken pipe */ +#define SOCEOS2ERR (SOCBASEERR+100) /* OS/2 Error */ +#define SOCEWOULDBLOCK (SOCBASEERR+35) /* Operation would block */ +#define SOCEINPROGRESS (SOCBASEERR+36) /* Operation now in progress */ +#define SOCEALREADY (SOCBASEERR+37) /* Operation already in progress */ +#define SOCENOTSOCK (SOCBASEERR+38) /* Socket operation on non-socket */ +#define SOCEDESTADDRREQ (SOCBASEERR+39) /* Destination address required */ +#define SOCEMSGSIZE (SOCBASEERR+40) /* Message too long */ +#define SOCEPROTOTYPE (SOCBASEERR+41) /* Protocol wrong type for socket */ +#define SOCENOPROTOOPT (SOCBASEERR+42) /* Protocol not available */ +#define SOCEPROTONOSUPPORT (SOCBASEERR+43) /* Protocol not supported */ +#define SOCESOCKTNOSUPPORT (SOCBASEERR+44) /* Socket type not supported */ +#define SOCEOPNOTSUPP (SOCBASEERR+45) /* Operation not supported on socket */ +#define SOCEPFNOSUPPORT (SOCBASEERR+46) /* Protocol family not supported */ +#define SOCEAFNOSUPPORT (SOCBASEERR+47) /* Address family not supported by protocol family */ +#define SOCEADDRINUSE (SOCBASEERR+48) /* Address already in use */ +#define SOCEADDRNOTAVAIL (SOCBASEERR+49) /* Can't assign requested address */ +#define SOCENETDOWN (SOCBASEERR+50) /* Network is down */ +#define SOCENETUNREACH (SOCBASEERR+51) /* Network is unreachable */ +#define SOCENETRESET (SOCBASEERR+52) /* Network dropped connection on reset */ +#define SOCECONNABORTED (SOCBASEERR+53) /* Software caused connection abort */ +#define SOCECONNRESET (SOCBASEERR+54) /* Connection reset by peer */ +#define SOCENOBUFS (SOCBASEERR+55) /* No buffer space available */ +#define SOCEISCONN (SOCBASEERR+56) /* Socket is already connected */ +#define SOCENOTCONN (SOCBASEERR+57) /* Socket is not connected */ +#define SOCESHUTDOWN (SOCBASEERR+58) /* Can't send after socket shutdown */ +#define SOCETOOMANYREFS (SOCBASEERR+59) /* Too many references: can't splice */ +#define SOCETIMEDOUT (SOCBASEERR+60) /* Connection timed out */ +#define SOCECONNREFUSED (SOCBASEERR+61) /* Connection refused */ +#define SOCELOOP (SOCBASEERR+62) /* Too many levels of symbolic links */ +#define SOCENAMETOOLONG (SOCBASEERR+63) /* File name too long */ +#define SOCEHOSTDOWN (SOCBASEERR+64) /* Host is down */ +#define SOCEHOSTUNREACH (SOCBASEERR+65) /* No route to host */ +#define SOCENOTEMPTY (SOCBASEERR+66) /* Directory not empty */ + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ + || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ + || (s) == APR_OS_START_SYSERR + SOCENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ + || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ + || (s) == APR_OS_START_SYSERR + SOCEWOULDBLOCK \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + SOCEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + SOCENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + SOCECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + SOCEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + SOCECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + SOCECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + SOCEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + SOCENETUNREACH) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE \ + || (s) == APR_OS_START_SYSERR + SOCEPIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_AFNOSUPPORT \ + || (s) == APR_OS_START_SYSERR + SOCEAFNOSUPPORT) + +/* + Sorry, too tired to wrap this up for OS2... feel free to + fit the following into their best matches. + + { ERROR_NO_SIGNAL_SENT, ESRCH }, + { SOCEALREADY, EALREADY }, + { SOCEDESTADDRREQ, EDESTADDRREQ }, + { SOCEMSGSIZE, EMSGSIZE }, + { SOCEPROTOTYPE, EPROTOTYPE }, + { SOCENOPROTOOPT, ENOPROTOOPT }, + { SOCEPROTONOSUPPORT, EPROTONOSUPPORT }, + { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT }, + { SOCEOPNOTSUPP, EOPNOTSUPP }, + { SOCEPFNOSUPPORT, EPFNOSUPPORT }, + { SOCEADDRINUSE, EADDRINUSE }, + { SOCEADDRNOTAVAIL, EADDRNOTAVAIL }, + { SOCENETDOWN, ENETDOWN }, + { SOCENETRESET, ENETRESET }, + { SOCENOBUFS, ENOBUFS }, + { SOCEISCONN, EISCONN }, + { SOCENOTCONN, ENOTCONN }, + { SOCESHUTDOWN, ESHUTDOWN }, + { SOCETOOMANYREFS, ETOOMANYREFS }, + { SOCELOOP, ELOOP }, + { SOCEHOSTDOWN, EHOSTDOWN }, + { SOCENOTEMPTY, ENOTEMPTY }, + { SOCEPIPE, EPIPE } +*/ + +#elif defined(WIN32) && !defined(DOXYGEN) /* !defined(OS2) */ + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) +#define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) + +/* A special case, only socket calls require this: + */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) +#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_CANNOT_MAKE \ + || (s) == APR_OS_START_SYSERR + ERROR_CURRENT_DIRECTORY \ + || (s) == APR_OS_START_SYSERR + ERROR_DRIVE_LOCKED \ + || (s) == APR_OS_START_SYSERR + ERROR_FAIL_I24 \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_LOCKED \ + || (s) == APR_OS_START_SYSERR + ERROR_NETWORK_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ + || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ + || (s) == APR_OS_START_SYSERR + WSAENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_NETPATH \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_NET_NAME \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_PATHNAME \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DRIVE \ + || (s) == APR_OS_START_SYSERR + ERROR_DIRECTORY) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM \ + || (s) == APR_OS_START_SYSERR + ERROR_ARENA_TRASHED \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_MEMORY \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_BLOCK \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_QUOTA \ + || (s) == APR_OS_START_SYSERR + ERROR_OUTOFMEMORY) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ + || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_TARGET_HANDLE) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_ACCESS \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DATA \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_SEEK_ON_DEVICE \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_PROC_SLOTS \ + || (s) == APR_OS_START_SYSERR + ERROR_NESTING_NOT_ALLOWED \ + || (s) == APR_OS_START_SYSERR + ERROR_MAX_THRDS_REACHED \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ + || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + WSAEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + ERROR_NETNAME_DELETED \ + || (s) == APR_OS_START_SYSERR + WSAECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE \ + || (s) == APR_OS_START_SYSERR + ERROR_EXE_MACHINE_TYPE_MISMATCH \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DLL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_MODULETYPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_EXE_FORMAT \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_EXE_SIGNATURE \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_CORRUPT \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_FORMAT) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY) +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT \ + || (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT) + +#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */ + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define apr_get_os_error() (errno) +#define apr_set_os_error(e) (errno = (e)) + +/* A special case, only socket calls require this: */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) +#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) + +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == EWOULDBLOCK \ + || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + WSAEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + WSAECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) +#define APR_STATUS_IS_ENETDOWN(s) ((s) == APR_OS_START_SYSERR + WSAENETDOWN) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY) +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT \ + || (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT) + +#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ + +/* + * os error codes are clib error codes + */ +#define APR_FROM_OS_ERROR(e) (e) +#define APR_TO_OS_ERROR(e) (e) + +#define apr_get_os_error() (errno) +#define apr_set_os_error(e) (errno = (e)) + +/* A special case, only socket calls require this: + */ +#define apr_get_netos_error() (errno) +#define apr_set_netos_error(e) (errno = (e)) + +/** + * @addtogroup APR_STATUS_IS + * @{ + */ + +/** permission denied */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) +/** file exists */ +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) +/** path name is too long */ +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) +/** + * no such file or directory + * @remark + * EMVSCATLG can be returned by the automounter on z/OS for + * paths which do not exist. + */ +#ifdef EMVSCATLG +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == EMVSCATLG) +#else +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) +#endif +/** not a directory */ +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +/** no space left on device */ +#ifdef EDQUOT +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == EDQUOT) +#else +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) +#endif +/** not enough memory */ +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +/** too many open files */ +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) +/** file table overflow */ +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +/** bad file # */ +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) +/** invalid argument */ +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) +/** illegal seek */ +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) + +/** operation would block */ +#if !defined(EWOULDBLOCK) || !defined(EAGAIN) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) +#elif (EWOULDBLOCK == EAGAIN) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) +#else +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == EWOULDBLOCK) +#endif + +/** interrupted system call */ +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR) +/** socket operation on a non-socket */ +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK) +/** Connection Refused */ +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED) +/** operation now in progress */ +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS) + +/** + * Software caused connection abort + * @remark + * EPROTO on certain older kernels really means ECONNABORTED, so we need to + * ignore it for them. See discussion in new-httpd archives nh.9701 & nh.9603 + * + * There is potentially a bug in Solaris 2.x x<6, and other boxes that + * implement tcp sockets in userland (i.e. on top of STREAMS). On these + * systems, EPROTO can actually result in a fatal loop. See PR#981 for + * example. It's hard to handle both uses of EPROTO. + */ +#ifdef EPROTO +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == EPROTO) +#else +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED) +#endif + +/** Connection Reset by peer */ +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET) +/** Operation timed out + * @deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT) +/** no route to host */ +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH) +/** network is unreachable */ +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH) +/** inappropiate file type or format */ +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +/** broken pipe */ +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) +/** cross device link */ +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) +/** Directory Not Empty */ +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY || \ + (s) == APR_EEXIST) +/** Address Family not supported */ +#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT) +/** @} */ + +#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_ERRNO_H */ diff --git a/code/application/source/sf_app/code/include/apr_general.h b/code/application/source/sf_app/code/include/apr_general.h new file mode 100755 index 000000000..46883c9a0 --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_general.h @@ -0,0 +1,243 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_GENERAL_H +#define APR_GENERAL_H + +/** + * @file apr_general.h + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @brief APR Miscellaneous library routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#if APR_HAVE_SIGNAL_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_general Miscellaneous library routines + * @ingroup APR + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @{ + */ + +/** FALSE */ +#ifndef FALSE +#define FALSE 0 +#endif +/** TRUE */ +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/** a space */ +#define APR_ASCII_BLANK '\040' +/** a carrige return */ +#define APR_ASCII_CR '\015' +/** a line feed */ +#define APR_ASCII_LF '\012' +/** a tab */ +#define APR_ASCII_TAB '\011' + +/** signal numbers typedef */ +typedef int apr_signum_t; + +/** + * Finding offsets of elements within structures. + * Taken from the X code... they've sweated portability of this stuff + * so we don't have to. Sigh... + * @param p_type pointer type name + * @param field data field within the structure pointed to + * @return offset + */ + +#if defined(CRAY) || (defined(__arm) && !(defined(LINUX) || defined(__FreeBSD__))) +#ifdef __STDC__ +#define APR_OFFSET(p_type,field) _Offsetof(p_type,field) +#else +#ifdef CRAY2 +#define APR_OFFSET(p_type,field) \ + (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) + +#else /* !CRAY2 */ + +#define APR_OFFSET(p_type,field) ((unsigned int)&(((p_type)NULL)->field)) + +#endif /* !CRAY2 */ +#endif /* __STDC__ */ +#else /* ! (CRAY || __arm) */ + +#define APR_OFFSET(p_type,field) \ + ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) + +#endif /* !CRAY */ + +/** + * Finding offsets of elements within structures. + * @param s_type structure type name + * @param field data field within the structure + * @return offset + */ +#if defined(offsetof) && !defined(__cplusplus) +#define APR_OFFSETOF(s_type,field) offsetof(s_type,field) +#else +#define APR_OFFSETOF(s_type,field) APR_OFFSET(s_type*,field) +#endif + +#ifndef DOXYGEN + +/* A couple of prototypes for functions in case some platform doesn't + * have it + */ +#if (!APR_HAVE_STRCASECMP) && (APR_HAVE_STRICMP) +#define strcasecmp(s1, s2) stricmp(s1, s2) +#elif (!APR_HAVE_STRCASECMP) +int strcasecmp(const char *a, const char *b); +#endif + +#if (!APR_HAVE_STRNCASECMP) && (APR_HAVE_STRNICMP) +#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) +#elif (!APR_HAVE_STRNCASECMP) +//int strncasecmp(const char *a, const char *b, size_t n); +#endif + +#endif + +/** + * Alignment macros + */ + +/* APR_ALIGN() is only to be used to align on a power of 2 boundary */ +#define APR_ALIGN(size, boundary) \ + (((size) + ((boundary) - 1)) & ~((boundary) - 1)) + +/** Default alignment */ +#define APR_ALIGN_DEFAULT(size) APR_ALIGN(size, 8) + + +/** + * String and memory functions + */ + +/* APR_STRINGIFY is defined here, and also in apr_release.h, so wrap it */ +#ifndef APR_STRINGIFY +/** Properly quote a value as a string in the C preprocessor */ +#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n) +/** Helper macro for APR_STRINGIFY */ +#define APR_STRINGIFY_HELPER(n) #n +#endif + +#if (!APR_HAVE_MEMMOVE) +//#define memmove(a,b,c) bcopy(b,a,c) +#endif + +#if (!APR_HAVE_MEMCHR) +//void *memchr(const void *s, int c, size_t n); +#endif + +/** @} */ + +/** + * @defgroup apr_library Library initialization and termination + * @{ + */ + +/** + * Setup any APR internal data structures. This MUST be the first function + * called for any APR library. It is safe to call apr_initialize several + * times as long as apr_terminate is called the same number of times. + * @remark See apr_app_initialize if this is an application, rather than + * a library consumer of apr. + */ +//APR_DECLARE(apr_status_t) apr_initialize(void); + +/** + * Set up an application with normalized argc, argv (and optionally env) in + * order to deal with platform-specific oddities, such as Win32 services, + * code pages and signals. This must be the first function called for any + * APR program. + * @param argc Pointer to the argc that may be corrected + * @param argv Pointer to the argv that may be corrected + * @param env Pointer to the env that may be corrected, may be NULL + * @remark See apr_initialize if this is a library consumer of apr. + * Otherwise, this call is identical to apr_initialize, and must be closed + * with a call to apr_terminate at the end of program execution. + */ +/*APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, + char const * const * *argv, + char const * const * *env); +*/ +/** + * Tear down any APR internal data structures which aren't torn down + * automatically. apr_terminate must be called once for every call to + * apr_initialize() or apr_app_initialize(). + * @remark An APR program must call this function at termination once it + * has stopped using APR services. The APR developers suggest using + * atexit to ensure this is called. When using APR from a language + * other than C that has problems with the calling convention, use + * apr_terminate2() instead. + */ +//APR_DECLARE_NONSTD(void) apr_terminate(void); + +/** + * Tear down any APR internal data structures which aren't torn down + * automatically, same as apr_terminate + * @remark An APR program must call either the apr_terminate or apr_terminate2 + * function once it it has finished using APR services. The APR + * developers suggest using atexit(apr_terminate) to ensure this is done. + * apr_terminate2 exists to allow non-c language apps to tear down apr, + * while apr_terminate is recommended from c language applications. + */ +//APR_DECLARE(void) apr_terminate2(void); + +/** @} */ + +/** + * @defgroup apr_random Random Functions + * @{ + */ + +#if APR_HAS_RANDOM || defined(DOXYGEN) + +/* TODO: I'm not sure this is the best place to put this prototype...*/ +/** + * Generate random bytes. + * @param buf Buffer to fill with random bytes + * @param length Length of buffer in bytes + */ +APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf, + apr_size_t length); + +#endif +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_GENERAL_H */ diff --git a/code/application/source/sf_app/code/include/apr_lib.h b/code/application/source/sf_app/code/include/apr_lib.h new file mode 100755 index 000000000..03b9ee401 --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_lib.h @@ -0,0 +1,243 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_LIB_H +#define APR_LIB_H + +/** + * @file apr_lib.h + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @brief APR general purpose library routines + */ + +#include "apr.h" +#include "apr_errno.h" + +#if APR_HAVE_CTYPE_H +#include +#endif +#if APR_HAVE_STDARG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_lib General Purpose Library Routines + * @ingroup APR + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @{ + */ + +/** A constant representing a 'large' string. */ +#define HUGE_STRING_LEN 8192 + +/* + * Define the structures used by the APR general-purpose library. + */ + +/** @see apr_vformatter_buff_t */ +typedef struct apr_vformatter_buff_t apr_vformatter_buff_t; + +/** + * Structure used by the variable-formatter routines. + */ +struct apr_vformatter_buff_t { + /** The current position */ + char *curpos; + /** The end position of the format string */ + char *endpos; +}; + +/** + * return the final element of the pathname + * @param pathname The path to get the final element of + * @return the final element of the path + * @remark + *
+ * For example:
+ *                 "/foo/bar/gum"    -> "gum"
+ *                 "/foo/bar/gum/"   -> ""
+ *                 "gum"             -> "gum"
+ *                 "bs\\path\\stuff" -> "stuff"
+ * 
+ */ +//APR_DECLARE(const char *) apr_filepath_name_get(const char *pathname); + +/** + * apr_killpg + * Small utility macros to make things easier to read. Not usually a + * goal, to be sure.. + */ + +#ifdef WIN32 +#define apr_killpg(x, y) +#else /* WIN32 */ +#ifdef NO_KILLPG +#define apr_killpg(x, y) (kill (-(x), (y))) +#else /* NO_KILLPG */ +#define apr_killpg(x, y) (killpg ((x), (y))) +#endif /* NO_KILLPG */ +#endif /* WIN32 */ + +/** + * apr_vformatter() is a generic printf-style formatting routine + * with some extensions. + * @param flush_func The function to call when the buffer is full + * @param c The buffer to write to + * @param fmt The format string + * @param ap The arguments to use to fill out the format string. + * + * @remark + *
+ * The extensions are:
+ *
+ * - %%pA takes a struct in_addr *, and prints it as a.b.c.d
+ * - %%pI takes an apr_sockaddr_t * and prints it as a.b.c.d:port or
+ * \[ipv6-address\]:port
+ * - %%pT takes an apr_os_thread_t * and prints it in decimal
+ * ('0' is printed if !APR_HAS_THREADS)
+ * - %%pt takes an apr_os_thread_t * and prints it in hexadecimal
+ * ('0' is printed if !APR_HAS_THREADS)
+ * - %%pm takes an apr_status_t * and prints the appropriate error
+ * string (from apr_strerror) corresponding to that error code.
+ * - %%pp takes a void * and outputs it in hex
+ * - %%pB takes a apr_uint32_t * as bytes and outputs it's apr_strfsize
+ * - %%pF same as above, but takes a apr_off_t *
+ * - %%pS same as above, but takes a apr_size_t *
+ *
+ * %%pA, %%pI, %%pT, %%pp are available from APR 1.0.0 onwards (and in 0.9.x).
+ * %%pt is only available from APR 1.2.0 onwards.
+ * %%pm, %%pB, %%pF and %%pS are only available from APR 1.3.0 onwards.
+ *
+ * The %%p hacks are to force gcc's printf warning code to skip
+ * over a pointer argument without complaining.  This does
+ * mean that the ANSI-style %%p (output a void * in hex format) won't
+ * work as expected at all, but that seems to be a fair trade-off
+ * for the increased robustness of having printf-warnings work.
+ *
+ * Additionally, apr_vformatter allows for arbitrary output methods
+ * using the apr_vformatter_buff and flush_func.
+ *
+ * The apr_vformatter_buff has two elements curpos and endpos.
+ * curpos is where apr_vformatter will write the next byte of output.
+ * It proceeds writing output to curpos, and updating curpos, until
+ * either the end of output is reached, or curpos == endpos (i.e. the
+ * buffer is full).
+ *
+ * If the end of output is reached, apr_vformatter returns the
+ * number of bytes written.
+ *
+ * When the buffer is full, the flush_func is called.  The flush_func
+ * can return -1 to indicate that no further output should be attempted,
+ * and apr_vformatter will return immediately with -1.  Otherwise
+ * the flush_func should flush the buffer in whatever manner is
+ * appropriate, re apr_pool_t nitialize curpos and endpos, and return 0.
+ *
+ * Note that flush_func is only invoked as a result of attempting to
+ * write another byte at curpos when curpos >= endpos.  So for
+ * example, it's possible when the output exactly matches the buffer
+ * space available that curpos == endpos will be true when
+ * apr_vformatter returns.
+ *
+ * apr_vformatter does not call out to any other code, it is entirely
+ * self-contained.  This allows the callers to do things which are
+ * otherwise "unsafe".  For example, apr_psprintf uses the "scratch"
+ * space at the unallocated end of a block, and doesn't actually
+ * complete the allocation until apr_vformatter returns.  apr_psprintf
+ * would be completely broken if apr_vformatter were to call anything
+ * that used this same pool.  Similarly http_bprintf() uses the "scratch"
+ * space at the end of its output buffer, and doesn't actually note
+ * that the space is in use until it either has to flush the buffer
+ * or until apr_vformatter returns.
+ * 
+ +APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b), + apr_vformatter_buff_t *c, const char *fmt, + va_list ap); +*/ + +/** + * Display a prompt and read in the password from stdin. + * @param prompt The prompt to display + * @param pwbuf Buffer to store the password + * @param bufsize The length of the password buffer. + * @remark If the password entered must be truncated to fit in + * the provided buffer, APR_ENAMETOOLONG will be returned. + * Note that the bufsize paramater is passed by reference for no + * reason; its value will never be modified by the apr_password_get() + * function. + +APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, + apr_size_t *bufsize); +*/ + +/** @} */ + +/** + * @defgroup apr_ctype ctype functions + * These macros allow correct support of 8-bit characters on systems which + * support 8-bit characters. Pretty dumb how the cast is required, but + * that's legacy libc for ya. These new macros do not support EOF like + * the standard macros do. Tough. + * @{ + */ +/** @see isalnum */ +#define apr_isalnum(c) (isalnum(((unsigned char)(c)))) +/** @see isalpha */ +#define apr_isalpha(c) (isalpha(((unsigned char)(c)))) +/** @see iscntrl */ +#define apr_iscntrl(c) (iscntrl(((unsigned char)(c)))) +/** @see isdigit */ +#define apr_isdigit(c) (isdigit(((unsigned char)(c)))) +/** @see isgraph */ +#define apr_isgraph(c) (isgraph(((unsigned char)(c)))) +/** @see islower*/ +#define apr_islower(c) (islower(((unsigned char)(c)))) +/** @see isascii */ +#ifdef isascii +#define apr_isascii(c) (isascii(((unsigned char)(c)))) +#else +#define apr_isascii(c) (((c) & ~0x7f)==0) +#endif +/** @see isprint */ +#define apr_isprint(c) (isprint(((unsigned char)(c)))) +/** @see ispunct */ +#define apr_ispunct(c) (ispunct(((unsigned char)(c)))) +/** @see isspace */ +#define apr_isspace(c) (isspace(((unsigned char)(c)))) +/** @see isupper */ +#define apr_isupper(c) (isupper(((unsigned char)(c)))) +/** @see isxdigit */ +#define apr_isxdigit(c) (isxdigit(((unsigned char)(c)))) +/** @see tolower */ +#define apr_tolower(c) (tolower(((unsigned char)(c)))) +/** @see toupper */ +#define apr_toupper(c) (toupper(((unsigned char)(c)))) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_LIB_H */ diff --git a/code/application/source/sf_app/code/include/apr_pools.h b/code/application/source/sf_app/code/include/apr_pools.h new file mode 100755 index 000000000..2bb0822f2 --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_pools.h @@ -0,0 +1,817 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_POOLS_H +#define APR_POOLS_H + +/** + * @file apr_pools.h + * @brief APR memory allocation + * + * Resource allocation routines... + * + * designed so that we don't have to keep track of EVERYTHING so that + * it can be explicitly freed later (a fundamentally unsound strategy --- + * particularly in the presence of die()). + * + * Instead, we maintain pools, and allocate items (both memory and I/O + * handlers) from the pools --- currently there are two, one for + * per-transaction info, and one for config info. When a transaction is + * over, we can delete everything in the per-transaction apr_pool_t without + * fear, and without thinking too hard about it either. + * + * Note that most operations on pools are not thread-safe: a single pool + * should only be accessed by a single thread at any given time. The one + * exception to this rule is creating a subpool of a given pool: one or more + * threads can safely create subpools at the same time that another thread + * accesses the parent pool. + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_general.h" /* for APR_STRINGIFY */ +#define APR_WANT_MEMFUNC /**< for no good reason? */ +#include "apr_want.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_pools Memory Pool Functions + * @ingroup APR + * @{ + */ + +/** The fundamental pool type */ +typedef struct apr_pool_t apr_pool_t; + + +/** + * Declaration helper macro to construct apr_foo_pool_get()s. + * + * This standardized macro is used by opaque (APR) data types to return + * the apr_pool_t that is associated with the data type. + * + * APR_POOL_DECLARE_ACCESSOR() is used in a header file to declare the + * accessor function. A typical usage and result would be: + *
+ *    APR_POOL_DECLARE_ACCESSOR(file);
+ * becomes:
+ *    APR_DECLARE(apr_pool_t *) apr_file_pool_get(const apr_file_t *thefile);
+ * 
+ * @remark Doxygen unwraps this macro (via doxygen.conf) to provide + * actual help for each specific occurrence of apr_foo_pool_get. + * @remark the linkage is specified for APR. It would be possible to expand + * the macros to support other linkages. + */ +#define APR_POOL_DECLARE_ACCESSOR(type) \ + APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \ + (const apr_##type##_t *the##type) + +/** + * Implementation helper macro to provide apr_foo_pool_get()s. + * + * In the implementation, the APR_POOL_IMPLEMENT_ACCESSOR() is used to + * actually define the function. It assumes the field is named "pool". + */ +#define APR_POOL_IMPLEMENT_ACCESSOR(type) \ + APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \ + (const apr_##type##_t *the##type) \ + { return the##type->pool; } + + +/** + * Pool debug levels + * + *
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * ---------------------------------
+ * |   |   |   |   |   |   |   | x |  General debug code enabled (useful in
+ *                                    combination with --with-efence).
+ *
+ * |   |   |   |   |   |   | x |   |  Verbose output on stderr (report
+ *                                    CREATE, CLEAR, DESTROY).
+ *
+ * |   |   |   | x |   |   |   |   |  Verbose output on stderr (report
+ *                                    PALLOC, PCALLOC).
+ *
+ * |   |   |   |   |   | x |   |   |  Lifetime checking. On each use of a
+ *                                    pool, check its lifetime.  If the pool
+ *                                    is out of scope, abort().
+ *                                    In combination with the verbose flag
+ *                                    above, it will output LIFE in such an
+ *                                    event prior to aborting.
+ *
+ * |   |   |   |   | x |   |   |   |  Pool owner checking.  On each use of a
+ *                                    pool, check if the current thread is the
+ *                                    pool's owner.  If not, abort().  In
+ *                                    combination with the verbose flag above,
+ *                                    it will output OWNER in such an event
+ *                                    prior to aborting.  Use the debug
+ *                                    function apr_pool_owner_set() to switch
+ *                                    a pool's ownership.
+ *
+ * When no debug level was specified, assume general debug mode.
+ * If level 0 was specified, debugging is switched off.
+ * 
+ */ +#if defined(APR_POOL_DEBUG) +/* If APR_POOL_DEBUG is blank, we get 1; if it is a number, we get -1. */ +#if (APR_POOL_DEBUG - APR_POOL_DEBUG -1 == 1) +#undef APR_POOL_DEBUG +#define APR_POOL_DEBUG 1 +#endif +#else +#define APR_POOL_DEBUG 0 +#endif + +/** the place in the code where the particular function was called */ +#define APR_POOL__FILE_LINE__ __FILE__ ":" APR_STRINGIFY(__LINE__) + + +#if 0 +/** A function that is called when allocation fails. */ +typedef int (*apr_abortfunc_t)(int retcode); + +/* + * APR memory structure manipulators (pools, tables, and arrays). + */ + +/* + * Initialization + */ + +/** + * Setup all of the internal structures required to use pools + * @remark Programs do NOT need to call this directly. APR will call this + * automatically from apr_initialize. + * @internal + */ +//APR_DECLARE(apr_status_t) apr_pool_initialize(void); + +/** + * Tear down all of the internal structures required to use pools + * @remark Programs do NOT need to call this directly. APR will call this + * automatically from apr_terminate. + * @internal + */ +//APR_DECLARE(void) apr_pool_terminate(void); + + +/* + * Pool creation/destruction + */ + +//#include "apr_allocator.h" + +/** + * Create a new pool. + * @param newpool The pool we have just created. + * @param parent The parent pool. If this is NULL, the new pool is a root + * pool. If it is non-NULL, the new pool will inherit all + * of its parent pool's attributes, except the apr_pool_t will + * be a sub-pool. + * @param abort_fn A function to use if the pool cannot allocate more memory. + * @param allocator The allocator to use with the new pool. If NULL the + * allocator of the parent pool will be used. + * @remark This function is thread-safe, in the sense that multiple threads + * can safely create subpools of the same parent pool concurrently. + * Similarly, a subpool can be created by one thread at the same + * time that another thread accesses the parent pool. + */ +APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); + +/** + * Create a new pool. + * @deprecated @see apr_pool_create_unmanaged_ex. + */ +APR_DECLARE(apr_status_t) apr_pool_create_core_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator); + +/** + * Create a new unmanaged pool. + * @param newpool The pool we have just created. + * @param abort_fn A function to use if the pool cannot allocate more memory. + * @param allocator The allocator to use with the new pool. If NULL a + * new allocator will be created with the new pool as owner. + * @remark An unmanaged pool is a special pool without a parent; it will + * NOT be destroyed upon apr_terminate. It must be explicitly + * destroyed by calling apr_pool_destroy, to prevent memory leaks. + * Use of this function is discouraged, think twice about whether + * you really really need it. + * @warning Any child cleanups registered against the new pool, or + * against sub-pools thereof, will not be executed during an + * invocation of apr_proc_create(), so resources created in an + * "unmanaged" pool hierarchy will leak to child processes. + */ +APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); + +/** + * Debug version of apr_pool_create_ex. + * @param newpool @see apr_pool_create. + * @param parent @see apr_pool_create. + * @param abort_fn @see apr_pool_create. + * @param allocator @see apr_pool_create. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_create_ex + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_create_ex in a wrapper, trust the macro + * and don't call apr_pool_create_ex_debug directly. + */ +APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_create_ex(newpool, parent, abort_fn, allocator) \ + apr_pool_create_ex_debug(newpool, parent, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) +#endif + +/** + * Debug version of apr_pool_create_core_ex. + * @deprecated @see apr_pool_create_unmanaged_ex_debug. + */ +APR_DECLARE(apr_status_t) apr_pool_create_core_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line); + +/** + * Debug version of apr_pool_create_unmanaged_ex. + * @param newpool @see apr_pool_create_unmanaged. + * @param abort_fn @see apr_pool_create_unmanaged. + * @param allocator @see apr_pool_create_unmanaged. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_create_unmanaged_ex + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_create_core_ex in a wrapper, trust the macro + * and don't call apr_pool_create_core_ex_debug directly. + */ +APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_create_core_ex(newpool, abort_fn, allocator) \ + apr_pool_create_unmanaged_ex_debug(newpool, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) + +#define apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator) \ + apr_pool_create_unmanaged_ex_debug(newpool, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) + +#endif + +/** + * Create a new pool. + * @param newpool The pool we have just created. + * @param parent The parent pool. If this is NULL, the new pool is a root + * pool. If it is non-NULL, the new pool will inherit all + * of its parent pool's attributes, except the apr_pool_t will + * be a sub-pool. + * @remark This function is thread-safe, in the sense that multiple threads + * can safely create subpools of the same parent pool concurrently. + * Similarly, a subpool can be created by one thread at the same + * time that another thread accesses the parent pool. + */ +#if defined(DOXYGEN) +APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool, + apr_pool_t *parent); +#else +#if APR_POOL_DEBUG +#define apr_pool_create(newpool, parent) \ + apr_pool_create_ex_debug(newpool, parent, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#else +#define apr_pool_create(newpool, parent) \ + apr_pool_create_ex(newpool, parent, NULL, NULL) +#endif +#endif + +/** + * Create a new unmanaged pool. + * @param newpool The pool we have just created. + */ +#if defined(DOXYGEN) +APR_DECLARE(apr_status_t) apr_pool_create_core(apr_pool_t **newpool); +APR_DECLARE(apr_status_t) apr_pool_create_unmanaged(apr_pool_t **newpool); +#else +#if APR_POOL_DEBUG +#define apr_pool_create_core(newpool) \ + apr_pool_create_unmanaged_ex_debug(newpool, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#define apr_pool_create_unmanaged(newpool) \ + apr_pool_create_unmanaged_ex_debug(newpool, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#else +#define apr_pool_create_core(newpool) \ + apr_pool_create_unmanaged_ex(newpool, NULL, NULL) +#define apr_pool_create_unmanaged(newpool) \ + apr_pool_create_unmanaged_ex(newpool, NULL, NULL) +#endif +#endif + +/** + * Find the pool's allocator + * @param pool The pool to get the allocator from. + */ +APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + +/** + * Clear all memory in the pool and run all the cleanups. This also destroys all + * subpools. + * @param p The pool to clear + * @remark This does not actually free the memory, it just allows the pool + * to re-use this memory for the next allocation. + * @see apr_pool_destroy() + */ +APR_DECLARE(void) apr_pool_clear(apr_pool_t *p) __attribute__((nonnull(1))); + +/** + * Debug version of apr_pool_clear. + * @param p See: apr_pool_clear. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_clear + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_clear in a wrapper, trust the macro + * and don't call apr_pool_destroy_clear directly. + */ +APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_clear(p) \ + apr_pool_clear_debug(p, APR_POOL__FILE_LINE__) +#endif + +/** + * Destroy the pool. This takes similar action as apr_pool_clear() and then + * frees all the memory. + * @param p The pool to destroy + * @remark This will actually free the memory + */ +APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1))); + +/** + * Debug version of apr_pool_destroy. + * @param p See: apr_pool_destroy. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have your apr_pool_destroy + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_destroy in a wrapper, trust the macro + * and don't call apr_pool_destroy_debug directly. + */ +APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pool_destroy(p) \ + apr_pool_destroy_debug(p, APR_POOL__FILE_LINE__) +#endif + + +/* + * Memory allocation + */ + +/** + * Allocate a block of memory from a pool + * @param p The pool to allocate from + * @param size The amount of memory to allocate + * @return The allocated memory + */ +APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(2))) +#endif + __attribute__((nonnull(1))); + +/** + * Debug version of apr_palloc + * @param p See: apr_palloc + * @param size See: apr_palloc + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @return See: apr_palloc + */ +APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(2))) +#endif + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_palloc(p, size) \ + apr_palloc_debug(p, size, APR_POOL__FILE_LINE__) +#endif + +/** + * Allocate a block of memory from a pool and set all of the memory to 0 + * @param p The pool to allocate from + * @param size The amount of memory to allocate + * @return The allocated memory + */ +#if defined(DOXYGEN) +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *p, apr_size_t size); +#elif !APR_POOL_DEBUG +#define apr_pcalloc(p, size) memset(apr_palloc(p, size), 0, size) +#endif + +/** + * Debug version of apr_pcalloc + * @param p See: apr_pcalloc + * @param size See: apr_pcalloc + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @return See: apr_pcalloc + */ +APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) + __attribute__((nonnull(1))); + +#if APR_POOL_DEBUG +#define apr_pcalloc(p, size) \ + apr_pcalloc_debug(p, size, APR_POOL__FILE_LINE__) +#endif + + +/* + * Pool Properties + */ + +/** + * Set the function to be called when an allocation failure occurs. + * @remark If the program wants APR to exit on a memory allocation error, + * then this function can be called to set the callback to use (for + * performing cleanup and then exiting). If this function is not called, + * then APR will return an error and expect the calling program to + * deal with the error accordingly. + */ +APR_DECLARE(void) apr_pool_abort_set(apr_abortfunc_t abortfunc, + apr_pool_t *pool) + __attribute__((nonnull(2))); + +/** + * Get the abort function associated with the specified pool. + * @param pool The pool for retrieving the abort function. + * @return The abort function for the given pool. + */ +APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + +/** + * Get the parent pool of the specified pool. + * @param pool The pool for retrieving the parent pool. + * @return The parent of the given pool. + */ +APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + +/** + * Determine if pool a is an ancestor of pool b. + * @param a The pool to search + * @param b The pool to search for + * @return True if a is an ancestor of b, NULL is considered an ancestor + * of all pools. + * @remark if compiled with APR_POOL_DEBUG, this function will also + * return true if A is a pool which has been guaranteed by the caller + * (using apr_pool_join) to have a lifetime at least as long as some + * ancestor of pool B. + */ +APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b); + +/** + * Tag a pool (give it a name) + * @param pool The pool to tag + * @param tag The tag + */ +APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag) + __attribute__((nonnull(1))); + + +/* + * User data management + */ + +/** + * Set the data associated with the current pool + * @param data The user data associated with the pool. + * @param key The key to use for association + * @param cleanup The cleanup program to use to cleanup the data (NULL if none) + * @param pool The current pool + * @warning The data to be attached to the pool should have a life span + * at least as long as the pool it is being attached to. + * + * Users of APR must take EXTREME care when choosing a key to + * use for their data. It is possible to accidentally overwrite + * data by choosing a key that another part of the program is using. + * Therefore it is advised that steps are taken to ensure that unique + * keys are used for all of the userdata objects in a particular pool + * (the same key in two different pools or a pool and one of its + * subpools is okay) at all times. Careful namespace prefixing of + * key names is a typical way to help ensure this uniqueness. + * + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_set(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); + +/** + * Set the data associated with the current pool + * @param data The user data associated with the pool. + * @param key The key to use for association + * @param cleanup The cleanup program to use to cleanup the data (NULL if none) + * @param pool The current pool + * @note same as apr_pool_userdata_set(), except that this version doesn't + * make a copy of the key (this function is useful, for example, when + * the key is a string literal) + * @warning This should NOT be used if the key could change addresses by + * any means between the apr_pool_userdata_setn() call and a + * subsequent apr_pool_userdata_get() on that key, such as if a + * static string is used as a userdata key in a DSO and the DSO could + * be unloaded and reloaded between the _setn() and the _get(). You + * MUST use apr_pool_userdata_set() in such cases. + * @warning More generally, the key and the data to be attached to the + * pool should have a life span at least as long as the pool itself. + * + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_setn( + const void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); + +/** + * Return the data associated with the current pool. + * @param data The user data associated with the pool. + * @param key The key for the data to retrieve + * @param pool The current pool. + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) + __attribute__((nonnull(1,2,3))); + + +/** + * @defgroup PoolCleanup Pool Cleanup Functions + * + * Cleanups are performed in the reverse order they were registered. That is: + * Last In, First Out. A cleanup function can safely allocate memory from + * the pool that is being cleaned up. It can also safely register additional + * cleanups which will be run LIFO, directly after the current cleanup + * terminates. Cleanups have to take caution in calling functions that + * create subpools. Subpools, created during cleanup will NOT automatically + * be cleaned up. In other words, cleanups are to clean up after themselves. + * + * @{ + */ + +/** + * Register a function to be called when a pool is cleared or destroyed + * @param p The pool to register the cleanup with + * @param data The data to pass to the cleanup function. + * @param plain_cleanup The function to call when the pool is cleared + * or destroyed + * @param child_cleanup The function to call when a child process is about + * to exec - this function is called in the child, obviously! + */ +APR_DECLARE(void) apr_pool_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); + +/** + * Register a function to be called when a pool is cleared or destroyed. + * + * Unlike apr_pool_cleanup_register which registers a cleanup + * that is called AFTER all subpools are destroyed, this function registers + * a function that will be called before any of the subpools are destroyed. + * + * @param p The pool to register the cleanup with + * @param data The data to pass to the cleanup function. + * @param plain_cleanup The function to call when the pool is cleared + * or destroyed + */ +APR_DECLARE(void) apr_pool_pre_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *)) + __attribute__((nonnull(3))); + +/** + * Remove a previously registered cleanup function. + * + * The cleanup most recently registered with @a p having the same values of + * @a data and @a cleanup will be removed. + * + * @param p The pool to remove the cleanup from + * @param data The data of the registered cleanup + * @param cleanup The function to remove from cleanup + * @remarks For some strange reason only the plain_cleanup is handled by this + * function + */ +APR_DECLARE(void) apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); + +/** + * Replace the child cleanup function of a previously registered cleanup. + * + * The cleanup most recently registered with @a p having the same values of + * @a data and @a plain_cleanup will have the registered child cleanup + * function replaced with @a child_cleanup. + * + * @param p The pool of the registered cleanup + * @param data The data of the registered cleanup + * @param plain_cleanup The plain cleanup function of the registered cleanup + * @param child_cleanup The function to register as the child cleanup + */ +APR_DECLARE(void) apr_pool_child_cleanup_set( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); + +/** + * Run the specified cleanup function immediately and unregister it. + * + * The cleanup most recently registered with @a p having the same values of + * @a data and @a cleanup will be removed and @a cleanup will be called + * with @a data as the argument. + * + * @param p The pool to remove the cleanup from + * @param data The data to remove from cleanup + * @param cleanup The function to remove from cleanup + */ +APR_DECLARE(apr_status_t) apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); + +/** + * An empty cleanup function. + * + * Passed to apr_pool_cleanup_register() when no cleanup is required. + * + * @param data The data to cleanup, will not be used by this function. + */ +APR_DECLARE_NONSTD(apr_status_t) apr_pool_cleanup_null(void *data); + +/** + * Run all registered child cleanups, in preparation for an exec() + * call in a forked child -- close files, etc., but *don't* flush I/O + * buffers, *don't* wait for subprocesses, and *don't* free any + * memory. + */ +APR_DECLARE(void) apr_pool_cleanup_for_exec(void); + +/** @} */ + +/** + * @defgroup PoolDebug Pool Debugging functions. + * + * pools have nested lifetimes -- sub_pools are destroyed when the + * parent pool is cleared. We allow certain liberties with operations + * on things such as tables (and on other structures in a more general + * sense) where we allow the caller to insert values into a table which + * were not allocated from the table's pool. The table's data will + * remain valid as long as all the pools from which its values are + * allocated remain valid. + * + * For example, if B is a sub pool of A, and you build a table T in + * pool B, then it's safe to insert data allocated in A or B into T + * (because B lives at most as long as A does, and T is destroyed when + * B is cleared/destroyed). On the other hand, if S is a table in + * pool A, it is safe to insert data allocated in A into S, but it + * is *not safe* to insert data allocated from B into S... because + * B can be cleared/destroyed before A is (which would leave dangling + * pointers in T's data structures). + * + * In general we say that it is safe to insert data into a table T + * if the data is allocated in any ancestor of T's pool. This is the + * basis on which the APR_POOL_DEBUG code works -- it tests these ancestor + * relationships for all data inserted into tables. APR_POOL_DEBUG also + * provides tools (apr_pool_find, and apr_pool_is_ancestor) for other + * folks to implement similar restrictions for their own data + * structures. + * + * However, sometimes this ancestor requirement is inconvenient -- + * sometimes it's necessary to create a sub pool where the sub pool is + * guaranteed to have the same lifetime as the parent pool. This is a + * guarantee implemented by the *caller*, not by the pool code. That + * is, the caller guarantees they won't destroy the sub pool + * individually prior to destroying the parent pool. + * + * In this case the caller must call apr_pool_join() to indicate this + * guarantee to the APR_POOL_DEBUG code. + * + * These functions are only implemented when #APR_POOL_DEBUG is set. + * + * @{ + */ +#if APR_POOL_DEBUG || defined(DOXYGEN) +/** + * Guarantee that a subpool has the same lifetime as the parent. + * @param p The parent pool + * @param sub The subpool + */ +APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub) + __attribute__((nonnull(2))); + +/** + * Find a pool from something allocated in it. + * @param mem The thing allocated in the pool + * @return The pool it is allocated in + */ +APR_DECLARE(apr_pool_t *) apr_pool_find(const void *mem); + +/** + * Report the number of bytes currently in the pool + * @param p The pool to inspect + * @param recurse Recurse/include the subpools' sizes + * @return The number of bytes + */ +APR_DECLARE(apr_size_t) apr_pool_num_bytes(apr_pool_t *p, int recurse) + __attribute__((nonnull(1))); + +/** + * Lock a pool + * @param pool The pool to lock + * @param flag The flag + */ +APR_DECLARE(void) apr_pool_lock(apr_pool_t *pool, int flag); + +/* @} */ + +#else /* APR_POOL_DEBUG or DOXYGEN */ + +#ifdef apr_pool_join +#undef apr_pool_join +#endif +#define apr_pool_join(a,b) + +#ifdef apr_pool_lock +#undef apr_pool_lock +#endif +#define apr_pool_lock(pool, lock) + +#endif /* APR_POOL_DEBUG or DOXYGEN */ + +/** @} */ + + +#endif +#ifdef __cplusplus +} +#endif + +#endif /* !APR_POOLS_H */ diff --git a/code/application/source/sf_app/code/include/apr_sha1.h b/code/application/source/sf_app/code/include/apr_sha1.h new file mode 100755 index 000000000..9bba8e048 --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_sha1.h @@ -0,0 +1,122 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* NIST Secure Hash Algorithm + * heavily modified by Uwe Hollerbach uh@alumni.caltech edu + * from Peter C. Gutmann's implementation as found in + * Applied Cryptography by Bruce Schneier + * This code is hereby placed in the public domain + */ + +#ifndef APR_SHA1_H +#define APR_SHA1_H + +#include "apu.h" +#include "apr_general.h" +#include "sf_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file apr_sha1.h + * @brief APR-UTIL SHA1 library + */ + +/** size of the SHA1 DIGEST */ +#define APR_SHA1_DIGESTSIZE 20 + +/** + * Define the Magic String prefix that identifies a password as being + * hashed using our algorithm. + */ +#define APR_SHA1PW_ID "{SHA}" + +/** length of the SHA Password */ +#define APR_SHA1PW_IDLEN 5 + +/** @see apr_sha1_ctx_t */ +typedef struct apr_sha1_ctx_t apr_sha1_ctx_t; + +/** + * SHA1 context structure + */ +struct apr_sha1_ctx_t { + /** message digest */ + UINT32 digest[5]; + /** 64-bit bit counts */ + UINT32 count_lo, count_hi; + /** SHA data buffer */ + UINT32 data[16]; + /** unprocessed amount in data */ + int local; +}; + +/** + * Provide a means to SHA1 crypt/encode a plaintext password in a way which + * makes password file compatible with those commonly use in netscape web + * and ldap installations. + * @param clear The plaintext password + * @param len The length of the plaintext password + * @param out The encrypted/encoded password + * @note SHA1 support is useful for migration purposes, but is less + * secure than Apache's password format, since Apache's (MD5) + * password format uses a random eight character salt to generate + * one of many possible hashes for the same password. Netscape + * uses plain SHA1 without a salt, so the same password + * will always generate the same hash, making it easier + * to break since the search space is smaller. + */ +APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out); + +/** + * Initialize the SHA digest + * @param context The SHA context to initialize + */ +APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *context); + +/** + * Update the SHA digest + * @param context The SHA1 context to update + * @param input The buffer to add to the SHA digest + * @param inputLen The length of the input buffer + */ +APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *context, const char *input, + unsigned int inputLen); + +/** + * Update the SHA digest with binary data + * @param context The SHA1 context to update + * @param input The buffer to add to the SHA digest + * @param inputLen The length of the input buffer + */ +APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *context, + const unsigned char *input, + unsigned int inputLen); + +/** + * Finish computing the SHA digest + * @param digest the output buffer in which to store the digest + * @param context The context to finalize + */ +APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE], + apr_sha1_ctx_t *context); + +#ifdef __cplusplus +} +#endif + +#endif /* APR_SHA1_H */ diff --git a/code/application/source/sf_app/code/include/apr_strings.h b/code/application/source/sf_app/code/include/apr_strings.h new file mode 100755 index 000000000..9dd029f1c --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_strings.h @@ -0,0 +1,390 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Portions of this file are covered by */ +/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef APR_STRINGS_H +#define APR_STRINGS_H + +/** + * @file apr_strings.h + * @brief APR Strings library + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_pools.h" +#define APR_WANT_IOVEC +#include "apr_want.h" + +#if APR_HAVE_STDARG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_strings String routines + * @ingroup APR + * @{ + */ + +/** + * Do a natural order comparison of two strings. + * @param a The first string to compare + * @param b The second string to compare + * @return Either <0, 0, or >0. If the first string is less than the second + * this returns <0, if they are equivalent it returns 0, and if the + * first string is greater than second string it retuns >0. + */ +//APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b); + +/** + * Do a natural order comparison of two strings ignoring the case of the + * strings. + * @param a The first string to compare + * @param b The second string to compare + * @return Either <0, 0, or >0. If the first string is less than the second + * this returns <0, if they are equivalent it returns 0, and if the + * first string is greater than second string it retuns >0. + */ +//APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b); + +/** + * duplicate a string into memory allocated out of a pool + * @param p The pool to allocate out of + * @param s The string to duplicate + * @return The new string or NULL if s == NULL + */ +//APR_DECLARE(char *) apr_pstrdup(apr_pool_t *p, const char *s); + +/** + * Create a null-terminated string by making a copy of a sequence + * of characters and appending a null byte + * @param p The pool to allocate out of + * @param s The block of characters to duplicate + * @param n The number of characters to duplicate + * @return The new string or NULL if s == NULL + * @remark This is a faster alternative to apr_pstrndup, for use + * when you know that the string being duplicated really + * has 'n' or more characters. If the string might contain + * fewer characters, use apr_pstrndup. + +APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(3))) +#endif + ; +*/ + +/** + * Duplicate at most n characters of a string into memory allocated + * out of a pool; the new string will be NUL-terminated + * @param p The pool to allocate out of + * @param s The string to duplicate + * @param n The maximum number of characters to duplicate + * @return The new string or NULL if s == NULL + * @remark The amount of memory allocated from the pool is the length + * of the returned string including the NUL terminator + */ +//APR_DECLARE(char *) apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); + +/** + * Duplicate a block of memory. + * + * @param p The pool to allocate from + * @param m The memory to duplicate + * @param n The number of bytes to duplicate + * @return The new block of memory or NULL if m == NULL + +APR_DECLARE(void *) apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) + __attribute__((alloc_size(3))) +#endif + ; +*/ + +/** + * Concatenate multiple strings, allocating memory out a pool + * @param p The pool to allocate out of + * @param ... The strings to concatenate. The final string must be NULL + * @return The new string + +APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, ...) +#if defined(__GNUC__) && __GNUC__ >= 4 + __attribute__((sentinel)) +#endif + ; +*/ + +/** + * Concatenate multiple strings specified in a writev-style vector + * @param p The pool from which to allocate + * @param vec The strings to concatenate + * @param nvec The number of strings to concatenate + * @param nbytes (output) strlen of new string (pass in NULL to omit) + * @return The new string + +APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *p, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); +*/ + +/** + * printf-style style printing routine. The data is output to a string + * allocated from a pool + * @param p The pool to allocate out of + * @param fmt The format of the string + * @param ap The arguments to use while printing the data + * @return The new string + */ +//APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); + +/** + * printf-style style printing routine. The data is output to a string + * allocated from a pool + * @param p The pool to allocate out of + * @param fmt The format of the string + * @param ... The arguments to use while printing the data + * @return The new string + +APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...) + __attribute__((format(printf,2,3))); +*/ + +/** + * Copy up to dst_size characters from src to dst; does not copy + * past a NUL terminator in src, but always terminates dst with a NUL + * regardless. + * @param dst The destination string + * @param src The source string + * @param dst_size The space available in dst; dst always receives + * NUL termination, so if src is longer than + * dst_size, the actual number of characters copied is + * dst_size - 1. + * @return Pointer to the NUL terminator of the destination string, dst + * @remark + *
+ * Note the differences between this function and strncpy():
+ *  1) strncpy() doesn't always NUL terminate; apr_cpystrn() does.
+ *  2) strncpy() pads the destination string with NULs, which is often 
+ *     unnecessary; apr_cpystrn() does not.
+ *  3) strncpy() returns a pointer to the beginning of the dst string;
+ *     apr_cpystrn() returns a pointer to the NUL terminator of dst, 
+ *     to allow a check for truncation.
+ * 
+ +APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src, + apr_size_t dst_size); +*/ + +/** + * Remove all whitespace from a string + * @param dest The destination string. It is okay to modify the string + * in place. Namely dest == src + * @param src The string to rid the spaces from. + * @return A pointer to the destination string's null terminator. + */ +//APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src); + +/** + * Convert the arguments to a program from one string to an array of + * strings terminated by a NULL pointer + * @param arg_str The arguments to convert + * @param argv_out Output location. This is a pointer to an array of strings. + * @param token_context Pool to use. + +APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str, + char ***argv_out, + apr_pool_t *token_context); +*/ + +/** + * Split a string into separate null-terminated tokens. The tokens are + * delimited in the string by one or more characters from the sep + * argument. + * @param str The string to separate; this should be specified on the + * first call to apr_strtok() for a given string, and NULL + * on subsequent calls. + * @param sep The set of delimiters + * @param last State saved by apr_strtok() between calls. + * @return The next token from the string + * @note the 'last' state points to the trailing NUL char of the final + * token, otherwise it points to the character following the current + * token (all successive or empty occurances of sep are skiped on the + * subsequent call to apr_strtok). Therefore it is possible to avoid + * a strlen() determination, with the following logic; + * toklen = last - retval; if (*last) --toklen; + */ +//APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last); + +/** + * @defgroup APR_Strings_Snprintf snprintf implementations + * @warning + * These are snprintf implementations based on apr_vformatter(). + * + * Note that various standards and implementations disagree on the return + * value of snprintf, and side-effects due to %n in the formatting string. + * apr_snprintf (and apr_vsnprintf) behaves as follows: + * + * Process the format string until the entire string is exhausted, or + * the buffer fills. If the buffer fills then stop processing immediately + * (so no further %n arguments are processed), and return the buffer + * length. In all cases the buffer is NUL terminated. It will return the + * number of characters inserted into the buffer, not including the + * terminating NUL. As a special case, if len is 0, apr_snprintf will + * return the number of characters that would have been inserted if + * the buffer had been infinite (in this case, *buffer can be NULL) + * + * In no event does apr_snprintf return a negative number. + * @{ + */ + +/** + * snprintf routine based on apr_vformatter. This means it understands the + * same extensions. + * @param buf The buffer to write to + * @param len The size of the buffer + * @param format The format string + * @param ... The arguments to use to fill out the format string. + +APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, + const char *format, ...) + __attribute__((format(printf,3,4))); +*/ + +/** + * vsnprintf routine based on apr_vformatter. This means it understands the + * same extensions. + * @param buf The buffer to write to + * @param len The size of the buffer + * @param format The format string + * @param ap The arguments to use to fill out the format string. + +APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, + va_list ap); +*/ +/** @} */ + +/** + * create a string representation of an int, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +//APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n); + +/** + * create a string representation of a long, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +//APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n); + +/** + * create a string representation of an apr_off_t, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +//APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n); + +/** + * Convert a numeric string into an apr_off_t numeric value. + * @param offset The value of the parsed string. + * @param buf The string to parse. It may contain optional whitespace, + * followed by an optional '+' (positive, default) or '-' (negative) + * character, followed by an optional '0x' prefix if base is 0 or 16, + * followed by numeric digits appropriate for base. + * @param end A pointer to the end of the valid character in buf. If + * not NULL, it is set to the first invalid character in buf. + * @param base A numeric base in the range between 2 and 36 inclusive, + * or 0. If base is zero, buf will be treated as base ten unless its + * digits are prefixed with '0x', in which case it will be treated as + * base 16. + * @bug *end breaks type safety; where *buf is const, *end needs to be + * declared as const in APR 2.0 + +APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *buf, + char **end, int base); +*/ + +/** + * parse a numeric string into a 64-bit numeric value + * @param buf The string to parse. It may contain optional whitespace, + * followed by an optional '+' (positive, default) or '-' (negative) + * character, followed by an optional '0x' prefix if base is 0 or 16, + * followed by numeric digits appropriate for base. + * @param end A pointer to the end of the valid character in buf. If + * not NULL, it is set to the first invalid character in buf. + * @param base A numeric base in the range between 2 and 36 inclusive, + * or 0. If base is zero, buf will be treated as base ten unless its + * digits are prefixed with '0x', in which case it will be treated as + * base 16. + * @return The numeric value of the string. On overflow, errno is set + * to ERANGE. On success, errno is set to 0. + */ +//APR_DECLARE(apr_int64_t) apr_strtoi64(const char *buf, char **end, int base); + +/** + * parse a base-10 numeric string into a 64-bit numeric value. + * Equivalent to apr_strtoi64(buf, (char**)NULL, 10). + * @param buf The string to parse + * @return The numeric value of the string. On overflow, errno is set + * to ERANGE. On success, errno is set to 0. + */ +//APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf); + +/** + * Format a binary size (magnitiudes are 2^10 rather than 10^3) from an apr_off_t, + * as bytes, K, M, T, etc, to a four character compacted human readable string. + * @param size The size to format + * @param buf The 5 byte text buffer (counting the trailing null) + * @return The buf passed to apr_strfsize() + * @remark All negative sizes report ' - ', apr_strfsize only formats positive values. + */ +//APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_STRINGS_H */ diff --git a/code/application/source/sf_app/code/include/apr_want.h b/code/application/source/sf_app/code/include/apr_want.h new file mode 100755 index 000000000..f48d3549b --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_want.h @@ -0,0 +1,126 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "apr.h" /* configuration data */ +/** + * @file apr_want.h + * @brief APR Standard Headers Support + * + *
+ * Features:
+ *
+ *   APR_WANT_STRFUNC:  strcmp, strcat, strcpy, etc
+ *   APR_WANT_MEMFUNC:  memcmp, memcpy, etc
+ *   APR_WANT_STDIO:     and related bits
+ *   APR_WANT_IOVEC:    struct iovec
+ *   APR_WANT_BYTEFUNC: htons, htonl, ntohl, ntohs
+ *
+ * Typical usage:
+ *
+ *   \#define APR_WANT_STRFUNC
+ *   \#define APR_WANT_MEMFUNC
+ *   \#include "apr_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ *       headers' or source files' use of apr_want.h)
+ * 
+ */ + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_STRFUNC + +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif + +#undef APR_WANT_STRFUNC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_MEMFUNC + +#if APR_HAVE_STRING_H +#include +#endif + +#undef APR_WANT_MEMFUNC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_STDIO + +#if APR_HAVE_STDIO_H +#include +#endif + +#undef APR_WANT_STDIO +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_IOVEC + +#if APR_HAVE_IOVEC + +#if APR_HAVE_SYS_UIO_H +#include +#endif + +#else + +#ifndef APR_IOVEC_DEFINED +#define APR_IOVEC_DEFINED +#if 0 +struct iovec +{ + void *iov_base; + size_t iov_len; +}; +#endif +#endif /* !APR_IOVEC_DEFINED */ + +#endif /* APR_HAVE_IOVEC */ + +#undef APR_WANT_IOVEC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_BYTEFUNC + +/* Single Unix says they are in arpa/inet.h. Linux has them in + * netinet/in.h. FreeBSD has them in arpa/inet.h but requires that + * netinet/in.h be included first. + */ +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif + +#undef APR_WANT_BYTEFUNC +#endif + +/* --------------------------------------------------------------------- */ diff --git a/code/application/source/sf_app/code/include/apr_xlate.h b/code/application/source/sf_app/code/include/apr_xlate.h new file mode 100755 index 000000000..5d98903de --- /dev/null +++ b/code/application/source/sf_app/code/include/apr_xlate.h @@ -0,0 +1,164 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 APR_XLATE_H +#define APR_XLATE_H + +#include "apu.h" +#include "apr_pools.h" +#include "apr_errno.h" + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file apr_xlate.h + * @brief APR I18N translation library + */ + +/** + * @defgroup APR_XLATE I18N translation library + * @ingroup APR + * @{ + */ +/** Opaque translation buffer */ +typedef struct apr_xlate_t apr_xlate_t; + +/** + * Set up for converting text from one charset to another. + * @param convset The handle to be filled in by this function + * @param topage The name of the target charset + * @param frompage The name of the source charset + * @param pool The pool to use + * @remark + * Specify APR_DEFAULT_CHARSET for one of the charset + * names to indicate the charset of the source code at + * compile time. This is useful if there are literal + * strings in the source code which must be translated + * according to the charset of the source code. + * APR_DEFAULT_CHARSET is not useful if the source code + * of the caller was not encoded in the same charset as + * APR at compile time. + * + * @remark + * Specify APR_LOCALE_CHARSET for one of the charset + * names to indicate the charset of the current locale. + * + * @remark + * Return APR_EINVAL if unable to procure a convset, or APR_ENOTIMPL + * if charset transcoding is not available in this instance of + * apr-util at all (i.e., APR_HAS_XLATE is undefined). + */ +APU_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset, + const char *topage, + const char *frompage, + apr_pool_t *pool); + +/** + * This is to indicate the charset of the sourcecode at compile time + * names to indicate the charset of the source code at + * compile time. This is useful if there are literal + * strings in the source code which must be translated + * according to the charset of the source code. + */ +#define APR_DEFAULT_CHARSET (const char *)0 +/** + * To indicate charset names of the current locale + */ +#define APR_LOCALE_CHARSET (const char *)1 + +/** + * Find out whether or not the specified conversion is single-byte-only. + * @param convset The handle allocated by apr_xlate_open, specifying the + * parameters of conversion + * @param onoff Output: whether or not the conversion is single-byte-only + * @remark + * Return APR_ENOTIMPL if charset transcoding is not available + * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined). + */ +APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff); + +/** + * Convert a buffer of text from one codepage to another. + * @param convset The handle allocated by apr_xlate_open, specifying + * the parameters of conversion + * @param inbuf The address of the source buffer + * @param inbytes_left Input: the amount of input data to be translated + * Output: the amount of input data not yet translated + * @param outbuf The address of the destination buffer + * @param outbytes_left Input: the size of the output buffer + * Output: the amount of the output buffer not yet used + * @remark + * Returns APR_ENOTIMPL if charset transcoding is not available + * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined). + * Returns APR_INCOMPLETE if the input buffer ends in an incomplete + * multi-byte character. + * + * To correctly terminate the output buffer for some multi-byte + * character set encodings, a final call must be made to this function + * after the complete input string has been converted, passing + * the inbuf and inbytes_left parameters as NULL. (Note that this + * mode only works from version 1.1.0 onwards) + */ +APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset, + const char *inbuf, + UINT32 *inbytes_left, + char *outbuf, + UINT32 *outbytes_left); + +/* @see apr_file_io.h the comment in apr_file_io.h about this hack */ +#ifdef APR_NOT_DONE_YET +/** + * The purpose of apr_xlate_conv_char is to translate one character + * at a time. This needs to be written carefully so that it works + * with double-byte character sets. + * @param convset The handle allocated by apr_xlate_open, specifying the + * parameters of conversion + * @param inchar The character to convert + * @param outchar The converted character + */ +APU_DECLARE(apr_status_t) apr_xlate_conv_char(apr_xlate_t *convset, + char inchar, char outchar); +#endif + +/** + * Convert a single-byte character from one charset to another. + * @param convset The handle allocated by apr_xlate_open, specifying the + * parameters of conversion + * @param inchar The single-byte character to convert. + * @warning This only works when converting between single-byte character sets. + * -1 will be returned if the conversion can't be performed. + */ +//APU_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset, + // unsigned char inchar); + +/** + * Close a codepage translation handle. + * @param convset The codepage translation handle to close + * @remark + * Return APR_ENOTIMPL if charset transcoding is not available + * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined). + */ +APU_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset); + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_XLATE_H */ diff --git a/code/application/source/sf_app/code/include/apu.h b/code/application/source/sf_app/code/include/apu.h new file mode 100755 index 000000000..450dfbff8 --- /dev/null +++ b/code/application/source/sf_app/code/include/apu.h @@ -0,0 +1,146 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * apu.h is duplicated from apu.hw at build time -- do not edit apu.h + */ +/* @file apu.h + * @brief APR-Utility main file + */ +/** + * @defgroup APR_Util APR Utility Functions + * @{ + */ + + +#ifndef APU_H +#define APU_H + +/** + * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library, + * so that all public symbols are exported. + * + * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers, + * to provide static linkage when the dynamic library may be unavailable. + * + * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when + * including the APR-UTIL public headers, to import and link the symbols from + * the dynamic APR-UTIL library and assure appropriate indirection and calling + * conventions at compile time. + */ + +/* Make sure we have our platform identifier macro defined we ask for later. + */ +#if defined(_WIN32) && !defined(WIN32) +#define WIN32 1 +#endif + +#if defined(DOXYGEN) || !defined(WIN32) +/** + * The public APR-UTIL functions are declared with APU_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APU_DECLARE_NONSTD(). + * + * @fn APU_DECLARE(rettype) apr_func(args); + */ +#define APU_DECLARE(type) type +/** + * The public APR-UTIL functions using variable arguments are declared with + * APU_DECLARE_NONSTD(), as they must use the C language calling convention. + * + * @fn APU_DECLARE_NONSTD(rettype) apr_func(args, ...); + */ +#define APU_DECLARE_NONSTD(type) type +/** + * The public APR-UTIL variables are declared with APU_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * + * @fn APU_DECLARE_DATA type apr_variable; + * @note extern APU_DECLARE_DATA type apr_variable; syntax is required for + * declarations within headers to properly import the variable. + */ +#define APU_DECLARE_DATA +#elif defined(APU_DECLARE_STATIC) +#define APU_DECLARE(type) type __stdcall +#define APU_DECLARE_NONSTD(type) type __cdecl +#define APU_DECLARE_DATA +#elif defined(APU_DECLARE_EXPORT) +#define APU_DECLARE(type) __declspec(dllexport) type __stdcall +#define APU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define APU_DECLARE_DATA __declspec(dllexport) +#else +#define APU_DECLARE(type) __declspec(dllimport) type __stdcall +#define APU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define APU_DECLARE_DATA __declspec(dllimport) +#endif + +#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC) +/** + * Declare a dso module's exported module structure as APU_MODULE_DECLARE_DATA. + * + * Unless APU_MODULE_DECLARE_STATIC is defined at compile time, symbols + * declared with APU_MODULE_DECLARE_DATA are always exported. + * @code + * module APU_MODULE_DECLARE_DATA mod_tag + * @endcode + */ +#define APU_MODULE_DECLARE_DATA +#else +#define APU_MODULE_DECLARE_DATA __declspec(dllexport) +#endif + +/* + * we always have SDBM (it's in our codebase) + */ +#define APU_HAVE_SDBM 1 + +#ifndef APU_DSO_MODULE_BUILD +#define APU_HAVE_GDBM 0 +#define APU_HAVE_NDBM 0 +#define APU_HAVE_DB 0 + +#if APU_HAVE_DB +#define APU_HAVE_DB_VERSION 0 +#endif +#endif + +/* + * we always enable dynamic driver loads within apr_dbd + * Win32 always has odbc (it's always installed) + */ +#ifndef APU_DSO_MODULE_BUILD +#define APU_HAVE_PGSQL 0 +#define APU_HAVE_MYSQL 0 +#define APU_HAVE_SQLITE3 0 +#define APU_HAVE_SQLITE2 0 +#define APU_HAVE_ORACLE 0 +#define APU_HAVE_FREETDS 0 +#define APU_HAVE_ODBC 1 +#endif + +#define APU_HAVE_CRYPTO 0 + +#ifndef APU_DSO_MODULE_BUILD +#define APU_HAVE_OPENSSL 0 +#define APU_HAVE_NSS 0 +#endif + +#define APU_HAVE_APR_ICONV 0 +#define APU_HAVE_ICONV 0 +#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV) + +#endif /* APU_H */ +/** @} */ diff --git a/code/application/source/sf_app/code/include/apu_config.h b/code/application/source/sf_app/code/include/apu_config.h new file mode 100755 index 000000000..b0e203932 --- /dev/null +++ b/code/application/source/sf_app/code/include/apu_config.h @@ -0,0 +1,52 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 is a Windows specific version of apu_config.hw. It is copied + * as apu_config.h at the start of a Windows build. + */ + +#ifdef WIN32 + +#ifndef APU_CONFIG_H +#define APU_CONFIG_H + +/* Compile win32 with DSO support for .dll builds */ +#ifdef APU_DECLARE_STATIC +#define APU_DSO_BUILD 0 +#else +#define APU_DSO_BUILD 1 +#endif + +/* Presume a standard, modern (5.x) mysql sdk/ +#define HAVE_MY_GLOBAL_H 1 + +/* my_sys.h is broken on VC/Win32, and apparently not required */ +/* #undef HAVE_MY_SYS_H 0 */ + +/* + * Windows does not have GDBM, and we always use the bundled (new) Expat + */ + +/* Define if you have the gdbm library (-lgdbm). */ +/* #undef HAVE_LIBGDBM */ + +/* define if Expat 1.0 or 1.1 was found */ +/* #undef APR_HAVE_OLD_EXPAT */ + + +#endif /* APU_CONFIG_H */ +#endif /* WIN32 */ diff --git a/code/application/source/sf_app/code/include/bitstream.h b/code/application/source/sf_app/code/include/bitstream.h new file mode 100755 index 000000000..6aa545604 --- /dev/null +++ b/code/application/source/sf_app/code/include/bitstream.h @@ -0,0 +1,48 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __BITSTREAM_H__ +#define __BITSTREAM_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct { + int length; + unsigned char *data; +} BitStream; + +extern BitStream *BitStream_new(void); +extern int BitStream_append(BitStream *bstream, BitStream *arg); +extern int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num); +extern int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data); +#define BitStream_size(__bstream__) (__bstream__->length) +extern unsigned char *BitStream_toByte(BitStream *bstream); +extern void BitStream_free(BitStream *bstream); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __BITSTREAM_H__ */ diff --git a/code/application/source/sf_app/code/include/cJSON.h b/code/application/source/sf_app/code/include/cJSON.h new file mode 100755 index 000000000..53017090b --- /dev/null +++ b/code/application/source/sf_app/code/include/cJSON.h @@ -0,0 +1,276 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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. +*/ + +#ifndef cJSON__h +#define cJSON__h +#include "sf_type.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 1 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + SINT32 valueSINT32; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type __stdcall +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall +#endif +#else /* !WIN32 */ +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check if the item is a string and return its valuestring */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(SINT32 num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/arrray that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateSINT32Array(const SINT32 *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + + +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const SINT32 number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valueSINT32 too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valueSINT32 = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(SINT32) cJSON_SetNumberHelper(cJSON *object, SINT32 number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (SINT32)number) : (number)) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/application/source/sf_app/code/include/mask.h b/code/application/source/sf_app/code/include/mask.h new file mode 100755 index 000000000..934fa856f --- /dev/null +++ b/code/application/source/sf_app/code/include/mask.h @@ -0,0 +1,47 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MASK_H__ +#define __MASK_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int Mask_calcN2(int width, unsigned char *frame); +extern int Mask_calcN1N3(int length, int *runLength); +extern int Mask_calcRunLength(int width, unsigned char *frame, int dir, int *runLength); +extern int Mask_evaluateSymbol(int width, unsigned char *frame); +extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __MASK_H__ */ diff --git a/code/application/source/sf_app/code/include/mbedtls.h b/code/application/source/sf_app/code/include/mbedtls.h new file mode 100755 index 000000000..45839a71b --- /dev/null +++ b/code/application/source/sf_app/code/include/mbedtls.h @@ -0,0 +1,25941 @@ +/* + * MbedTLS Source Code Library Header + */ + + +#if 1//ME_COM_MBEDTLS +/* +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#endif +*/ + + + +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_PLATFORM_EXIT_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_PLATFORM_PRINTF_ALT + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#define MBEDTLS_CIPHER_PADDING_PKCS7 +//#define MBEDTLS_CIPHER_PADDING_PKCS5 + + +#define MBEDTLS_AES_ROM_TABLES + + + + + + + +#if 0 //modified by ljy 20220330 + + + +/********* Start of file include/mbedtls/config.h ************/ + +/** + * \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. + * \{ + */ + +/** + * \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_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \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_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_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. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_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 Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \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. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + */ +//#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 +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#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 + +/** + * \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_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \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. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * 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 + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +#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). + */ +#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/rsa_internal.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. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#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. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#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 up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#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 + * library/rsa_internal.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 up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#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 /**< 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 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_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_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'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/* \} 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 + +/* + * 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 + + + +#endif /* MBEDTLS_CONFIG_H */ + + + + +#endif //lijiayong + + +/********* Start of file include/mbedtls/check_config.h ************/ + +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.pl. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ + + +/********* Start of file include/mbedtls/platform.h ************/ + +/** + * \file platform.h + * + * \brief The Mbed TLS platform abstraction layer. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(_WIN32) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void * (*mbedtls_calloc)( size_t n, size_t size ); +extern void (*mbedtls_free)( void *ptr ); + +/** + * \brief This function allows configuring custom memory-management functions. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function allows configuring a custom \p fprintf function pointer. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function allows configuring a custom \c printf function + * pointer. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(_WIN32) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom \c snprintf function + * pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf snprintf +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function allows configuring a custom \c exit function + * pointer. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct { + char dummy; /**< Placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else + +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform initialization operations. + * + * \param ctx The Mbed TLS context. + * + * \return \c 0 on success. + * + * \note This function is intended to allow platform-specific initialization, + * and should be called before any other library functions. Its + * implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * Its use and whether it is necessary to call it is dependent on the + * platform. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \param ctx The Mbed TLS context. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * Its use and whether it is necessary to call it is dependent on the + * platform. + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ + + +/********* Start of file include/mbedtls/platform_time.h ************/ + +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ + + +/********* Start of file include/mbedtls/threading.h ************/ + +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * 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_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct +{ + pthread_mutex_t mutex; + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ + + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ + + +/********* Start of file include/mbedtls/bignum.h ************/ + +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * 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_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mbedtls_mpi value + * \param Y Second mbedtls_mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param buf Buffer to write the string to + * \param buflen Length of buf + * \param olen Length of the string written, including final NUL byte + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with buflen = 0 to obtain the + * minimum required buffer size in *olen. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read MPI from a line in an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * MBEDTLS_ERR_MPI_XXX error code + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix 16. + * + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The unsigned integer value to multiply with + * + * \note b is unsigned + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); + +/** + * \brief Division by mbedtls_mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination mbedtls_mpi_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * + * \note The bytes obtained from the PRNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, + MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ + + +/********* Start of file include/mbedtls/net.h ************/ + +/** + * \file net.h + * + * \brief Deprecated header file that includes mbedtls/net_sockets.h + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +/********* Start of file include/mbedtls/net_sockets.h ************/ + +/** + * \file net_sockets.h + * + * \brief Network communication functions + */ +/* + * 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_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return the number of bytes received, + * or a non-zero error code: + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ + + +/********* Start of file include/mbedtls/dhm.h ************/ + +/** + * \file dhm.h + * + * \brief Diffie-Hellman-Merkle key exchange. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The DHM context structure. + */ +typedef struct +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the ServerKeyExchange parameters. + * + * \param ctx The DHM context. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function sets up and writes the ServerKeyExchange + * parameters. + * + * \param ctx The DHM context. + * \param x_size The private value size in Bytes. + * \param olen The number of characters written. + * \param output The destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The destination buffer must be large enough to hold + * the reduced binary presentation of the modulus, the generator + * and the public key, each wrapped with a 2-byte length field. + * It is the responsibility of the caller to ensure that enough + * space is available. Refer to \c mbedtls_mpi_size to computing + * the byte-size of an MPI. + * + * \note This function assumes that \c ctx->P and \c ctx->G + * have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set prime modulus and generator + * + * \param ctx The DHM context. + * \param P The MPI holding DHM prime modulus. + * \param G The MPI holding DHM generator. + * + * \note This function can be used to set P, G + * in preparation for \c mbedtls_dhm_make_params. + * + * \return \c 0 if successful, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the public value G^Y of the peer. + * + * \param ctx The DHM context. + * \param input The input buffer. + * \param ilen The size of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates its own private value \c X and + * exports \c G^X. + * + * \param ctx The DHM context. + * \param x_size The private value size in Bytes. + * \param output The destination buffer. + * \param olen The length of the destination buffer. Must be at least + equal to ctx->len (the size of \c P). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The destination buffer will always be fully written + * so as to contain a big-endian presentation of G^X mod P. + * If it is larger than ctx->len, it will accordingly be + * padded with zero-bytes in the beginning. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \param ctx The DHM context. + * \param output The destination buffer. + * \param output_size The size of the destination buffer. Must be at least + * the size of ctx->len. + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + * + * \note If non-NULL, \p f_rng is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our secret value \p X is re-used and omitted + * otherwise. Therefore, we recommend always passing a + * non-NULL \p f_rng argument. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function frees and clears the components of a DHM key. + * + * \param ctx The DHM context to free and clear. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to initialize. + * \param dhmin The input buffer. + * \param dhminlen The size of the buffer, including the terminating null + * Byte for PEM data. + * + * \return \c 0 on success, or a specific DHM or PEM error code + * on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup x509_module */ +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * \param path The filename to read the DHM parameters from. + * + * \return \c 0 on success, or a specific DHM or PEM error code + * on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DHM_ALT */ + +#endif /* MBEDTLS_DHM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_constant_t) ( VAL ) ) +#else +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#endif /* ! MBEDTLS_DEPRECATED_WARNING */ + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ + + +/********* Start of file include/mbedtls/error.h ************/ + +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * 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_ERROR_H +#define MBEDTLS_ERROR_H + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 4 0x0020-0x0022 0x0023-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 11 0x0042-0x0052 0x0043-0x0045 + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 + * SHA256 1 0x0037-0x0037 + * SHA512 1 0x0039-0x0039 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 9 (Started from top) + * MD 5 5 + * CIPHER 6 8 + * SSL 6 17 (Started from top) + * SSL 7 31 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ + + +/********* Start of file include/mbedtls/md.h ************/ + + /** + * \file md.h + * + * \brief The generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Enumeration of supported message digests + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, + MBEDTLS_MD_MD2, + MBEDTLS_MD_MD4, + MBEDTLS_MD_MD5, + MBEDTLS_MD_SHA1, + MBEDTLS_MD_SHA224, + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_SHA512, + MBEDTLS_MD_RIPEMD160, +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct { + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name, + * or NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type, + * or NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \returns \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, + * #MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac
  • 0: HMAC is not used. Saves some memory.
  • + *
  • non-zero: HMAC is used with this context.
+ * + * \returns \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, or + * #MBEDTLS_ERR_MD_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, or + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ + + +/********* Start of file include/mbedtls/md_internal.h ************/ + +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * 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_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function in bytes */ + int size; + + /** Block length of the digest function in bytes */ + int block_size; + + /** Digest initialisation function */ + int (*starts_func)( void *ctx ); + + /** Digest update function */ + int (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + int (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + int (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Clone state from a context */ + void (*clone_func)( void *dst, const void *src ); + + /** Internal use only */ + int (*process_func)( void *ctx, const unsigned char *input ); +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ + + +/********* Start of file include/mbedtls/md5.h ************/ + +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * 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_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD5_ALT */ + +#endif /* MBEDTLS_MD5_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ + + +/********* Start of file include/mbedtls/md2.h ************/ + +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * 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_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD2_ALT */ + +#endif /* MBEDTLS_MD2_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ + + +/********* Start of file include/mbedtls/md4.h ************/ + +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * 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_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD4_ALT */ + +#endif /* MBEDTLS_MD4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ + + +/********* Start of file include/mbedtls/rsa.h ************/ + +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem. + * + * For more information, see Public-Key Cryptography Standards (PKCS) + * #1 v1.5: RSA Encryption and Public-Key Cryptography Standards + * (PKCS) #1 v2.1: RSA Cryptography Specifications. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS-1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS-1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct +{ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< \p D % (P - 1) */ + mbedtls_mpi DQ; /*!< \p D % (Q - 1) */ + mbedtls_mpi QP; /*!< 1 / (Q % P) */ + + mbedtls_mpi RN; /*!< cached R^2 mod \p N */ + + mbedtls_mpi RP; /*!< cached R^2 mod \p P */ + mbedtls_mpi RQ; /*!< cached R^2 mod \p Q */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx The RSA context to initialize. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of #mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overriden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overriden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overriden. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param P The first prime factor of \p N, or NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param D The private exponent, or NULL. + * \param E The public exponent, or NULL. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \return \c 0 on success, or a non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param N_len The Byte length of \p N, ignored if \p N == NULL. + * \param P The first prime factor of \p N, or NULL. + * \param P_len The Byte length of \p P, ignored if \p P == NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. + * \param D The private exponent, or NULL. + * \param D_len The Byte length of \p D, ignored if \p D == NULL. + * \param E The public exponent, or NULL. + * \param E_len The Byte length of \p E, ignored if \p E == NULL. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \return \c 0 on success, or a non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success, or #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the + * attempted derivations failed. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus, or NULL. + * \param P The MPI to hold the first prime factor of \p N, or NULL. + * \param Q The MPI to hold the second prime factor of \p N, or NULL. + * \param D The MPI to hold the private exponent, or NULL. + * \param E The MPI to hold the public exponent, or NULL. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies, + * or a non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, or NULL. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, or + * NULL. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, or + NULL. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, or NULL. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, or NULL. + * \param E_len The size of the buffer for the public exponent. + * + * \note The length fields are ignored if the corresponding + * buffer pointers are NULL. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies, + * or a non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold D modulo P-1, or NULL. + * \param DQ The MPI to hold D modulo Q-1, or NULL. + * \param QP The MPI to hold modular inverse of Q modulo P, or NULL. + * + * \return \c 0 on success, non-zero error code otherwise. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The RSA context to be set. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \param ctx The RSA context used to hold the key. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent. For example, 65537. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code on + * failure. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The RSA context holding the public key. + * \param prv The RSA context holding the private key. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The RSA context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for blinding. + * \param p_rng The RNG parameter. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 + * encoding, and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The input and output buffers must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 + * encoding and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer used to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. + * \param src The source context. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA Context to free. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RSA_ALT */ + +#endif /* MBEDTLS_RSA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ + + +/********* Start of file include/mbedtls/rsa_internal.h ************/ + +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * + * This file declares some RSA-related helper functions useful when + * implementing the RSA interface. They are public and provided in a + * separate compilation unit in order to make it easy for designers of + * alternative RSA implementations to use them in their code, as it is + * conceived that the functionality they provide will be necessary + * for most complete implementations. + * + * End-users of Mbed TLS not intending to re-implement the RSA functionality + * are not expected to get into the need of making use of these functions directly, + * but instead should be able to use the functions declared in rsa.h. + * + * There are two classes of helper functions: + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters + * and generates some other, or CRT related parameters. + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters + * and check their validity. + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); +#ifdef __cplusplus +} +#endif + + +#endif /* rsa_internal.h */ + + +/********* Start of file include/mbedtls/asn1.h ************/ + +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * 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_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \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 MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 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 MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ + + +/********* Start of file include/mbedtls/ecp.h ************/ + +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + */ +/* + * 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_ECP_H +#define MBEDTLS_ECP_H + + + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< ECP hardware accelerator failed. */ + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain parameters (curve, subgroup and generator) identifiers. + * + * Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, + MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ + MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} mbedtls_ecp_group_id; + +/** + * Number of supported curves (plus one for NONE). + * + * (Montgomery curves excluded for now.) + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/** + * Curve information for use by other modules + */ +typedef struct +{ + mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ + uint16_t tls_id; /*!< TLS NamedCurve identifier */ + uint16_t bit_size; /*!< Curve size in bits */ + const char *name; /*!< Human-friendly name */ +} mbedtls_ecp_curve_info; + +/** + * \brief ECP point structure (jacobian coordinates) + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or Z == 1. (Other + * values of Z are used by internal functions only.) + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, X and Y are its standard (affine) coordinates. + */ +typedef struct +{ + mbedtls_mpi X; /*!< the point's X coordinate */ + mbedtls_mpi Y; /*!< the point's Y coordinate */ + mbedtls_mpi Z; /*!< the point's Z coordinate */ +} +mbedtls_ecp_point; + +/** + * \brief ECP group structure + * + * We consider two types of curves equations: + * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) + * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) + * In both cases, a generator G for a prime-order subgroup is fixed. In the + * short weierstrass, this subgroup is actually the whole curve, and its + * cardinal is denoted by N. + * + * In the case of Short Weierstrass curves, our code requires that N is an odd + * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) + * + * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is + * the quantity actually used in the formulas. Also, nbits is not the size of N + * but the required size for private keys. + * + * If modp is NULL, reduction modulo P is done using a generic algorithm. + * Otherwise, it must point to a function that takes an mbedtls_mpi in the range + * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more + * than pbits, so that the integer may be efficiently brought in the 0..P-1 + * range by a few additions or substractions. It must return 0 on success and + * non-zero on failure. + */ +typedef struct +{ + mbedtls_ecp_group_id id; /*!< internal group identifier */ + mbedtls_mpi P; /*!< prime modulus of the base field */ + mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ + mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ + mbedtls_ecp_point G; /*!< generator of the (sub)group used */ + mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ + unsigned int h; /*!< internal: 1 if the constants are static */ + int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ + void *t_data; /*!< unused */ + mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ + size_t T_size; /*!< number for pre-computed points */ +} +mbedtls_ecp_group; + +/** + * \brief ECP key pair structure + * + * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * + * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * Maximum size of the groups (that is, of N and P) + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ + +/** + * \brief Get the list of supported curves in order of preferrence + * (full information) + * + * \return A statically allocated array, the last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief Get the list of supported curves in order of preferrence + * (grp_id only) + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief Get curve information from an internal group identifier + * + * \param grp_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief Get curve information from a TLS NamedCurve value + * + * \param tls_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief Get curve information from a human-readable name + * + * \param name The name + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief Initialize a point (as zero) + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief Initialize a group (to something meaningless) + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief Initialize a key pair (as an invalid one) + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief Free the components of a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief Free the components of an ECP group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief Free the components of a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +/** + * \brief Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief Copy the contents of a group object + * + * \param dst Destination group + * \param src Source group + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); + +/** + * \brief Set a point to zero + * + * \param pt Destination point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief Tell if a point is zero + * + * \param pt Point to test + * + * \return 1 if point is zero, 0 otherwise + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief Compare two points + * + * \note This assumes the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P First point to compare + * \param Q Second point to compare + * + * \return 0 if the points are equal, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief Import a non-zero point from two ASCII strings + * + * \param P Destination point + * \param radix Input numeric base + * \param x First affine coordinate as a null-terminated string + * \param y Second affine coordinate as a null-terminated string + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief Export a point into unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to export + * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro + * \param olen Length of the actual output + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + * \note This function does NOT check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() for + * that. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief Import a point from a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Destination point + * \param buf $(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after the ECPoint on exit + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief Export a point as a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Point to export + * \param format Export format + * \param olen length of data written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Set a group using well-known domain parameters + * + * \param grp Destination group + * \param id Index in the list of well-known domain parameters + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * + * \note Index should be a value of RFC 4492's enum NamedCurve, + * usually in the form of a MBEDTLS_ECP_DP_XXX macro. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief Set a group from a TLS ECParameters record + * + * \param grp Destination group + * \param buf &(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after ECParameters on exit + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); + +/** + * \brief Write the TLS ECParameters record for a group + * + * \param grp ECP group used + * \param olen Number of bytes actually written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Multiplication by an integer: R = m * P + * (Not thread-safe to use same group in multiple threads) + * + * \note In order to prevent timing attacks, this function + * executes the exact same sequence of (base field) + * operations for any valid m. It avoids any if-branch or + * array index depending on the value of m. + * + * \note If f_rng is not NULL, it is used to randomize intermediate + * results in order to prevent potential timing attacks + * targeting these results. It is recommended to always + * provide a non-NULL f_rng (the overhead is negligible). + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey + * or P is not a valid pubkey, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Multiplication and addition of two points by integers: + * R = m * P + n * Q + * (Not thread-safe to use same group in multiple threads) + * + * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee + * a constant execution flow and timing. + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply P + * \param P Point to multiply by m + * \param n Integer by which to multiply Q + * \param Q Point to be multiplied by n + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey + * or P or Q is not a valid pubkey, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); + +/** + * \brief Check that an mbedtls_mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); + +/** + * \brief Generate a keypair with configurable base point + * + * \param grp ECP group + * \param G Chosen base point + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp_id ECP group identifier + * \param key Destination keypair + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check a public-private key pair + * + * \param pub Keypair structure holding a public key + * \param prv Keypair structure holding a private (plus public) key + * + * \return 0 if successful (keys are valid and match), or + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or + * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_ALT */ + +#endif /* ecp.h */ + + +/********* Start of file include/mbedtls/ecdsa.h ************/ + +/** + * \file ecdsa.h + * + * \brief The Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * ECDSA is defined in Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_ECDSA_H +#define MBEDTLS_ECDSA_H + + + + +/* + * RFC-4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if MBEDTLS_ECP_MAX_BYTES > 124 +#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" +#endif +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) + +/** + * \brief The ECDSA context structure. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version is usually preferred. + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param md_alg The MD algorithm used to hash the message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \param grp The ECP group. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param Q The public key to use for verification. + * \param r The first integer of the signature. + * \param s The second integer of the signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + * + * \see ecp.h + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \param ctx The ECDSA context. + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes it to a buffer, + * serialized as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) and + * Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 + * + * \param ctx The ECDSA context. + * \param hash The Message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param md_alg The MD algorithm used to hash the message. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if a + * 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The size of the hash. + * \param sig The signature to read and verify. + * \param slen The size of \p sig. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than \p siglen, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + * + * \see ecp.h + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \param ctx The ECDSA context to store the keypair in. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on + * failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets an ECDSA context from an EC key pair. + * + * \param ctx The ECDSA context to set. + * \param key The EC key to use. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on + * failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ + + +/********* Start of file include/mbedtls/ecjpake.h ************/ + +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * 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_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ + + + + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +/** + * \brief Initialize a context + * (just makes it ready for setup() or free()). + * + * \param ctx context to initialize + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up a context for use + * + * \note Currently the only values for hash/curve allowed by the + * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx context to set up + * \param role Our role: client or server + * \param hash hash function to use (MBEDTLS_MD_XXX) + * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX) + * \param secret pre-shared secret (passphrase) + * \param len length of the shared secret + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Check if a context is ready for use + * + * \param ctx Context to check + * + * \return 0 if the context is ready for use, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes) + * + * \param ctx Context to use + * \param buf Pointer to extension contents + * \param len Extension length + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange) + * + * \param ctx Context to use + * \param buf Pointer to the message + * \param len Message length + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Free a context's content + * + * \param ctx context to free + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECJPAKE_ALT */ + +#endif /* MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* ecjpake.h */ + + +/********* Start of file include/mbedtls/pk.h ************/ + +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * 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_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#if defined(MBEDTLS_RSA_C) + +#endif + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a mbedtls_pk_context (as NONE) + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \return 0 if context can't do the operations, + * 1 otherwise. + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use - must hold a private key + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use - must hold a private key + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or MBEDTLS_PK_NONE + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ + + +/********* Start of file include/mbedtls/pk_internal.h ************/ + +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * 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_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ + + +/********* Start of file include/mbedtls/x509.h ************/ + +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * 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_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +#if defined(MBEDTLS_RSA_C) + +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) + +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ + + +/********* Start of file include/mbedtls/x509_crl.h ************/ + +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * 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_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ + + +/********* Start of file include/mbedtls/x509_crt.h ************/ + +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * 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_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs (see note above) + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 (and flags set to 0) if the chain was verified and valid, + * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified + * but found to be invalid, in which case *flags will have one + * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX + * flags set, or another error (and flags set to 0xffffffff) + * in case of a fatal error encountered during the + * verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ + + +/********* Start of file include/mbedtls/x509_csr.h ************/ + +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * 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_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *key; + mbedtls_asn1_named_data *subject; + mbedtls_md_type_t md_alg; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ + + +/********* Start of file include/mbedtls/cipher.h ************/ + +/** + * \file cipher.h + * + * \brief The generic cipher wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief An enumeration of supported ciphers. + * + * \warning ARC4 and DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, + MBEDTLS_CIPHER_ID_NULL, + MBEDTLS_CIPHER_ID_AES, + MBEDTLS_CIPHER_ID_DES, + MBEDTLS_CIPHER_ID_3DES, + MBEDTLS_CIPHER_ID_CAMELLIA, + MBEDTLS_CIPHER_ID_BLOWFISH, + MBEDTLS_CIPHER_ID_ARC4, +} mbedtls_cipher_id_t; + +/** + * \brief An enumeration of supported (cipher, mode) pairs. + * + * \warning ARC4 and DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, + MBEDTLS_CIPHER_NULL, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_CIPHER_CAMELLIA_256_CCM, +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, + MBEDTLS_MODE_ECB, + MBEDTLS_MODE_CBC, + MBEDTLS_MODE_CFB, + MBEDTLS_MODE_OFB, /* Unused! */ + MBEDTLS_MODE_CTR, + MBEDTLS_MODE_GCM, + MBEDTLS_MODE_STREAM, + MBEDTLS_MODE_CCM, +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in Bytes. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct { + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Flags to set. For example, if the cipher supports variable IV sizes or variable key sizes. */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct { + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported by the generic + * cipher module. + * + * \return A statically-allocated array of ciphers. The last entry + * is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_name, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes and fills the cipher-context + * structure with the appropriate values. It also clears + * the structure. + * + * \param ctx The context to initialize. May not be NULL. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, + * #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context failed. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The size of the blocks of the cipher, or zero if \p ctx + * has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The mode of operation, or #MBEDTLS_MODE_NONE if + * \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return
  • If no IV has been set: the recommended IV size. + * 0 for ciphers not using IV or nonce.
  • + *
  • If IV has already been set: the actual size.
+ */ +static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of the cipher, or #MBEDTLS_CIPHER_NONE if + * \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The name of the cipher, or NULL if \p ctx has not + * been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The key length of the cipher in bits, or + * #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or + * #MBEDTLS_DECRYPT, or #MBEDTLS_OPERATION_NONE if \p ctx + * has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. May not be NULL. Must have + * been initialized using mbedtls_cipher_info_from_type() + * or mbedtls_cipher_info_from_string(). + * \param key The key to use. + * \param key_bitlen The key length to use, in bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, or a cipher-specific + * error code. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. + * \param mode The padding mode. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Only supported with GCM. Must be called + * exactly once, after mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. + * \param ad The additional data to use. + * \param ad_len the Length of \p ad. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \param ctx The generic cipher context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher, or a cipher-specific + * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * function, except the last one before + * mbedtls_cipher_finish(). Must have \p ilen as a + * multiple of the block_size. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. + * \param output The buffer to write data to. Needs block_size available. + * \param olen The length of the data written to the \p output buffer. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, + * #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or a cipher-specific error code + * on failure for any other reason. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer to write the tag to. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, or + * #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or a cipher-specific error code on + * failure for any other reason. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer for the authentication tag. + * \param tag_len The desired length of the authentication tag. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * a cipher-specific error code. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief The generic autenticated decryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer holding the authentication tag. + * \param tag_len The length of the authentication tag. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic, + * or a cipher-specific error code on failure for any other reason. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ + + +/********* Start of file include/mbedtls/cipher_internal.h ************/ + +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * 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_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ + + +/********* Start of file include/mbedtls/ssl_ciphersuites.h ************/ + +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * 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_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int id; + const char * name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ + + +/********* Start of file include/mbedtls/ecdh.h ************/ + +/** + * \file ecdh.h + * + * \brief The Elliptic Curve Diffie-Hellman (ECDH) protocol APIs. + * + * ECDH is an anonymous key agreement protocol allowing two parties to + * establish a shared secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_ECDH_H +#define MBEDTLS_ECDH_H + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key: + *
  • Our key.
  • + *
  • The key of the peer.
+ */ +typedef enum +{ + MBEDTLS_ECDH_OURS, + MBEDTLS_ECDH_THEIRS, +} mbedtls_ecdh_side; + +/** + * \brief The ECDH context structure. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +} +mbedtls_ecdh_context; + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \param grp The ECP group. + * \param d The destination MPI (private key). + * \param Q The destination point (public key). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \param grp The ECP group. + * \param z The destination MPI (shared secret). + * \param Q The public key from another party. + * \param d Our secret exponent (private key). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks. For more information, see mbedtls_ecp_mul(). + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates a public key and a TLS + * ServerKeyExchange payload. + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context. + * \param olen The number of characters written. + * \param buf The destination buffer. + * \param blen The length of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note This function assumes that the ECP group (grp) of the + * \p ctx context has already been properly set, + * for example, using mbedtls_ecp_group_load(). + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes a TLS ServerKeyExhange + * payload. + * + * This is the first function used by a TLS client for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context. + * \param buf The pointer to the start of the input buffer. + * \param end The address for one Byte past the end of the buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \param ctx The ECDH context to set up. + * \param key The EC key to use. + * \param side Defines the source of the key: + *
  • 1: Our key.
  • +
  • 0: The key of the peer.
+ * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and a TLS + * ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \param ctx The ECDH context. + * \param olen The number of Bytes written. + * \param buf The destination buffer. + * \param blen The size of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes a TLS ClientKeyExchange + * payload. + * + * This is the second function used by a TLS server for ECDH(E) + * ciphersuites. + * + * \param ctx The ECDH context. + * \param buf The start of the input buffer. + * \param blen The length of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \param ctx The ECDH context. + * \param olen The number of Bytes written. + * \param buf The destination buffer. + * \param blen The length of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks. For more information, see mbedtls_ecp_mul(). + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ + + +/********* Start of file include/mbedtls/sha1.h ************/ + +/** + * \file sha1.h + * + * \brief The SHA-1 cryptographic hash function. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +/** + * \brief This function initializes a SHA-1 context. + * + * \param ctx The SHA-1 context to initialize. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \param ctx The SHA-1 context to clear. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \param dst The destination context. + * \param src The context to clone. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \param ctx The context to initialize. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only) + * + * \param ctx SHA-1 context + * \param data The data block being processed. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief SHA-1 context setup + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0 + * + * \param ctx The SHA-1 context to be initialized. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA1_ALT */ + +#endif /* MBEDTLS_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = SHA-1( input buffer ) + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-1 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ + + +/********* Start of file include/mbedtls/sha256.h ************/ + +/** + * \file sha256.h + * + * \brief The SHA-224 and SHA-256 cryptographic hash function. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use. +
  • 0: Use SHA-256.
  • +
  • 1: Use SHA-224.
*/ +} +mbedtls_sha256_context; + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to initialize. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return \c 0 on success. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224 or SHA-256 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224or SHA-256 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA256_ALT */ + +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ + + +/********* Start of file include/mbedtls/sha512.h ************/ + +/** + * \file sha512.h + * + * \brief The SHA-384 and SHA-512 cryptographic hash function. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ + int is384; /*!< Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
*/ +} +mbedtls_sha512_context; + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA512_ALT */ + +#endif /* MBEDTLS_SHA512_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ + + +/********* Start of file include/mbedtls/aes.h ************/ + +/** + * \file aes.h + * + * \brief The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + */ +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0023-0x0025 */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The AES context-type definition. + */ +typedef struct +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The encryption key. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + * on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The decryption key. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the AES block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must keep the maximum use of your counter in mind. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_AES_ALT */ + +#endif /* MBEDTLS_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ + + +/********* Start of file include/mbedtls/aesni.h ************/ + +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + */ +/* + * 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_AESNI_H +#define MBEDTLS_AESNI_H + + + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES-NI features detection routine + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief AES-NI AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief GCM multiplication: c = a * b in GF(2^128) + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Compute decryption round keys from encryption round keys + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ); + +/** + * \brief Perform key expansion (for encryption) + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ + + +/********* Start of file include/mbedtls/arc4.h ************/ + +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * 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_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ARC4_ALT */ + +#endif /* MBEDTLS_ARC4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ + + +/********* Start of file include/mbedtls/base64.h ************/ + +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * 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_BASE64_H +#define MBEDTLS_BASE64_H + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ + + +/********* Start of file include/mbedtls/bn_mul.h ************/ + +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * 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) + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + + + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * gcc -O0 by default uses r7 for the frame pointer, so it complains about our + * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, + * passing that option is not easy when building with yotta. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ + + +/********* Start of file include/mbedtls/camellia.h ************/ + +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * 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_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CAMELLIA context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +/** + * \brief Initialize CAMELLIA context + * + * \param ctx CAMELLIA context to be initialized + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear CAMELLIA context + * + * \param ctx CAMELLIA context to be cleared + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief CAMELLIA key schedule (encryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA key schedule (decryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key decryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA-ECB block encryption/decryption + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief CAMELLIA-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief CAMELLIA-CFB128 buffer encryption/decryption + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief CAMELLIA-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. + * + * \param ctx CAMELLIA context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_CAMELLIA_ALT */ + +#endif /* MBEDTLS_CAMELLIA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ + + +/********* Start of file include/mbedtls/ctr_drbg.h ************/ + +/** + * \file ctr_drbg.h + * + * \brief CTR_DRBG is based on AES-256, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic + * Random Bit Generators. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them using the compiler command + * line. + * \{ + */ + +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 +/**< The amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ +#else +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +/**< Amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ +#endif +#endif + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation. */ + int reseed_interval; /*!< The reseed interval. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * \note Personalization data can be provided in addition to the more generic + * entropy source, to make this instantiation as unique as possible. + * + * \param ctx The CTR_DRBG context to seed. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + length of the buffer. + * \param p_entropy The entropy context. + * \param custom Personalization data, that is device-specific + identifiers. Can be NULL. + * \param len The length of the personalization data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function clears CTR_CRBG context data. + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. The default value is + * #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be NULL. + * \param len The length of the additional data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + * + * \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, + * only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + */ +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * \param additional Additional data to update. Can be NULL. + * \param add_len The length of the additional data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +/* Internal functions (do not call directly) */ +int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ + + +/********* Start of file include/mbedtls/des.h ************/ + +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * 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_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DES_ALT */ + +#endif /* MBEDTLS_DES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ + + +/********* Start of file include/mbedtls/entropy.h ************/ + +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) + +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR + +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#if defined(MBEDTLS_HAVEGE_C) + +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct +{ + int accumulator_started; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTSL_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ + + +/********* Start of file include/mbedtls/entropy_poll.h ************/ + +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ + + +/********* Start of file include/mbedtls/havege.h ************/ + +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * 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_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct +{ + int PT1, PT2, offset[2]; + int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + int WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ + + +/********* Start of file include/mbedtls/memory_buffer_alloc.h ************/ + +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * 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_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ + + +/********* Start of file include/mbedtls/padlock.h ************/ + +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + */ +/* + * 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_PADLOCK_H +#define MBEDTLS_PADLOCK_H + + + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PadLock detection routine + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief PadLock AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief PadLock AES-CBC buffer en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ + + +/********* Start of file include/mbedtls/timing.h ************/ + +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * 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_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_TIMING_ALT */ + +#endif /* MBEDTLS_TIMING_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ + + +/********* Start of file include/mbedtls/xtea.h ************/ + +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * 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_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief XTEA context structure + */ +typedef struct +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_XTEA_ALT */ + +#endif /* MBEDTLS_XTEA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ + + +/********* Start of file include/mbedtls/ssl.h ************/ + +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * 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_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + + + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + +#endif + +#if defined(MBEDTLS_DHM_C) + +#endif + +#if defined(MBEDTLS_ECDH_C) + +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maxium fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +/* + * This structure is used for storing current session data. + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items by size (largest first) to minimize padding overhead */ + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello veirifcation */ + int (*f_cookie_write)( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*f_cookie_check)( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *p_cookie; /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*f_ticket_write)( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *p_ticket; /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + /** Callback to export key block and master secret */ + int (*f_export_keys)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t ); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< pre-shared key */ + size_t psk_len; /*!< length of the pre-shared key */ + unsigned char *psk_identity; /*!< identity for PSK negotiation */ + size_t psk_identity_len;/*!< length of identity */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + + /* + * Numerical settings (int then char) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (bitfields) + */ + + unsigned int endpoint : 1; /*!< 0: client, 1: server */ + unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned int mfl_code : 3; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + unsigned int anti_replay : 1; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + unsigned int session_tickets : 1; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + unsigned int fallback : 1; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +}; + + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif + + mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ + mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *f_recv_timeout; + /*!< Callback for network receive with timeout */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already splitted? */ +#endif + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif + void *appData; +}; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 +#define MBEDTLS_SSL_CHANNEL_INBOUND 1 + +extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); +extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Returns the list of ciphersuites supported by the SSL/TLS module. + * + * \return a statically allocated array of ciphersuites, the last + * entry is 0. + */ +const int *mbedtls_ssl_list_ciphersuites( void ); + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c mbedtls_x509_crt_verify() + * + * \param conf SSL configuration + * \param f_vrfy verification function + * \param p_vrfy verification parameter + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_sent_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \param f_export_keys Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 + * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + */ +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case mutliple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the expected identity name + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note Currently clients can only register one pre-shared key. + * In other words, the servers' identity hint is ignored. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature but + * feedback is welcomed. + * + * \param conf SSL configuration + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + + +/** + * \brief Set the Pre Shared Key (PSK) for the current handshake + * + * \note This should only be called inside the PSK callback, + * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the + * correct PSK and return 0. + * Any other return value will result in a denied PSK identity. + * + * \note If you set a PSK callback using this function, then you + * don't need to set a PSK key and identity using + * \c mbedtls_ssl_conf_psk(). + * + * \param conf SSL configuration + * \param f_psk PSK identity function + * \param p_psk PSK identity parameter + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * + * \return 0 if successful + */ +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \param conf SSL configuration + * \param bitlen Minimum bit length of the DHM prime + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * (Default: all available hashes except MD5.) + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ); +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param conf SSL configuration + * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + */ +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will likely be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \param conf SSL configuration + * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED + */ +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or + * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + */ +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or + * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or ingoing) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Return the number of data bytes available to read + * + * \param ssl SSL context + * + * \return how many bytes are available in the read buffer + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl SSL context + * + * \return 0 if successful, + * -1 if result is not available (eg because the handshake was + * aborted too early), or + * a combination of BADCERT_xxx and BADCRL_xxx flags, see + * x509.h + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is + * enabled, which makes expansion much less predictable + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes). + * This is the value negotiated with peer if any, + * or the locally configured value. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * \warning Currently, peer certificate is lost in the operation. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or + * a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after execution of this function. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * a specific SSL error code. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return the number of bytes read, or + * 0 for EOF, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or + * another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has beeen reset internally). Either way, you + * should make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return the number of bytes actually written (may be less than len), + * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, + * or another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a positive value. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_max_frag_len() may be used to query the + * active maximum fragment length. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevent fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ + + +/********* Start of file include/mbedtls/ssl_cookie.h ************/ + +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * 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_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct +{ + mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long serial; /*!< serial number for expiration */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ + + +/********* Start of file include/mbedtls/ssl_internal.h ************/ + +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * 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_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + + + + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) +#define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else +#define MBEDTLS_SSL_COMPRESSION_ADD 0 +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ + + MBEDTLS_SSL_COMPRESSION_ADD \ + + MBEDTLS_MAX_IV_LENGTH \ + + MBEDTLS_SSL_MAC_ADD \ + + MBEDTLS_SSL_PADDING_ADD \ + ) + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error Bad configuration - record content too large. +#endif + +#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048 +#error Bad configuration - protected record payload too large. +#endif + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#define MBEDTLS_SSL_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) ) + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + int sni_authmode; /*!< authmode from SNI callback */ + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + unsigned char *hs_msg; /*!< Reassembled handshake message */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + unsigned char retransmit_state; /*!< Retransmission state */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context fin_sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context fin_sha512; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif +}; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length (bytes) */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); + +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl SSL context to use + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); +#endif + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 13 ); +#else + ((void) ssl); +#endif + return( 5 ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +/* constant-time buffer comparison */ +static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_internal.h */ + + +/********* Start of file include/mbedtls/ssl_cache.h ************/ + +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * 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_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t timestamp; /*!< entry timestamp */ +#endif + mbedtls_ssl_session session; /*!< entry session */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ +#endif + mbedtls_ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ + + +/********* Start of file include/mbedtls/ssl_ticket.h ************/ + +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * 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_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct +{ + unsigned char name[4]; /*!< random key identifier */ + uint32_t generation_time; /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct +{ + mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ + unsigned char active; /*!< index of the currently active key */ + + uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonnable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedlts_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedlts_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ + + +/********* Start of file include/mbedtls/debug.h ************/ + +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * 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_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ + + + +/********* Start of file include/mbedtls/blowfish.h ************/ + +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * 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_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Blowfish context structure + */ +typedef struct +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +/** + * \brief Initialize Blowfish context + * + * \param ctx Blowfish context to be initialized + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear Blowfish context + * + * \param ctx Blowfish context to be cleared + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Blowfish key schedule + * + * \param ctx Blowfish context to be initialized + * \param key encryption key + * \param keybits must be between 32 and 448 bits + * + * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Blowfish-ECB block encryption/decryption + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Blowfish-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (8 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Blowfish CFB buffer encryption/decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Blowfish-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * \param ctx Blowfish context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 64-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* blowfish.h */ + + +/********* Start of file include/mbedtls/ccm.h ************/ + +/** + * \file ccm.h + * + * \brief CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CCM_H +#define MBEDTLS_CCM_H + + + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success, or a cipher-specific error code. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \param ctx The CCM context to use for encryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \return \c 0 on success. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector. + * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag in Bytes. + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return 0 if successful and authenticated, or + * #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_CCM_ALT */ + +#endif /* MBEDTLS_CCM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ + + +/********* Start of file include/mbedtls/gcm.h ************/ + +/** + * \file gcm.h + * + * \brief Galois/Counter Mode (GCM) for 128-bit block ciphers, as defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_GCM_H +#define MBEDTLS_GCM_H + + + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#if !defined(MBEDTLS_GCM_ALT) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The GCM context structure. + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success, or a cipher specific error code. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the input buffer. + * For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context to use for encryption or decryption. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return 0 if successful and authenticated, or + * #MBEDTLS_ERR_GCM_AUTH_FAILED if tag does not match. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or NULL if \p add_len is 0. + * \param add_len The length of the additional data. If 0, \p add is NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. + * \param tag The buffer for holding the tag. + * \param tag_len The length of the tag to generate. Must be at least four. + * + * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* !MBEDTLS_GCM_ALT */ + +#endif /* !MBEDTLS_GCM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ + + +/********* Start of file include/mbedtls/pem.h ************/ + +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * 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_PEM_H +#define MBEDTLS_PEM_H + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required + * size. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ + + +/********* Start of file include/mbedtls/asn1write.h ************/ + +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * 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_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + + + +#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ + g += ret; } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * \param oid_len length of the OID + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + +/** + * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ + + +/********* Start of file include/mbedtls/hmac_drbg.h ************/ + +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + */ +/* + * 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_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct +{ + /* Working state: the key K is not stored explicitely, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization + * Makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or + * mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding + * Seed and setup entropy source for future reseeds. + * + * \param ctx HMAC_DRBG context to be seeded + * \param md_info MD algorithm to use for HMAC_DRBG + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \note The "security strength" as defined by NIST is set to: + * 128 bits if md_alg is SHA-1, + * 192 bits if md_alg is SHA-224, + * 256 bits if md_alg is SHA-256 or higher. + * Note that SHA-256 is just as efficient as SHA-224. + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * (For use with deterministic ECDSA.) + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx HMAC_DRBG context + * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each reseed + * (Default: given by the security strength, which + * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) + * + * \param ctx HMAC_DRBG context + * \param len Amount of entropy to grab, in bytes + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) + * + * \param ctx HMAC_DRBG context + * \param interval Reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief HMAC_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (can be NULL) + * \param add_len Length of additional data (can be 0) + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param out_len Length of the buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ + + +/********* Start of file include/mbedtls/pkcs12.h ************/ + +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * 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_PKCS12_H +#define MBEDTLS_PKCS12_H + + + + + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ + + +/********* Start of file include/mbedtls/pkcs11.h ************/ + +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + */ +/* + * 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_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PKCS11_C) + + + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context for PKCS #11 private keys. + */ +typedef struct { + pkcs11h_certificate_t pkcs11h_cert; + int len; +} mbedtls_pkcs11_context; + +/** + * Initialize a mbedtls_pkcs11_context. + * (Just making memory references valid.) + */ +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the + * mbedtls_pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \param priv_key Private key structure to cleanup + */ +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + */ +static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +{ + return ( (mbedtls_pkcs11_context *) ctx )->len; +} + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PKCS11_C */ + +#endif /* MBEDTLS_PKCS11_H */ + + +/********* Start of file include/mbedtls/pkcs5.h ************/ + +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * 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_PKCS5_H +#define MBEDTLS_PKCS5_H + + + + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ + + +/********* Start of file include/mbedtls/oid.h ************/ + +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * 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_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +#include + +#if defined(MBEDTLS_CIPHER_C) + +#endif + +#if defined(MBEDTLS_MD_C) + +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ + +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct { + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ + + +/********* Start of file include/mbedtls/ripemd160.h ************/ + +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * 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_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RIPEMD160_ALT */ + +#endif /* MBEDTLS_RIPEMD160_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ + + +/********* Start of file include/mbedtls/version.h ************/ + +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * 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 defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 8 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02080000 +#define MBEDTLS_VERSION_STRING "2.8.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.8.0" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ + +#endif /* ME_COM_MBEDTLS */ diff --git a/code/application/source/sf_app/code/include/mmask.h b/code/application/source/sf_app/code/include/mmask.h new file mode 100755 index 000000000..f095727b1 --- /dev/null +++ b/code/application/source/sf_app/code/include/mmask.h @@ -0,0 +1,44 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MMASK_H__ +#define __MMASK_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int MMask_evaluateSymbol(int width, unsigned char *frame); +extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __MMASK_H__ */ diff --git a/code/application/source/sf_app/code/include/mqrspec.h b/code/application/source/sf_app/code/include/mqrspec.h new file mode 100755 index 000000000..71ff5f454 --- /dev/null +++ b/code/application/source/sf_app/code/include/mqrspec.h @@ -0,0 +1,167 @@ +/* + * qrencode - QR Code encoder + * + * Micro QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MQRSPEC_H__ +#define __MQRSPEC_H__ + +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define MQRSPEC_WIDTH_MAX 17 + +/** + * Return maximum data code length (bits) for the version. + * @param version + * @param level + * @return maximum size (bits) + */ +extern int MQRspec_getDataLengthBit(int version, QRecLevel level); + +/** + * Return maximum data code length (bytes) for the version. + * @param version + * @param level + * @return maximum size (bytes) + */ +extern int MQRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version + * @param level + * @return ECC size (bytes) + */ +extern int MQRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level + * @return version number + */ +extern int MQRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version + * @return width + */ +extern int MQRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version + * @return number of remainder bits + */ +extern int MQRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of lenght indicator for the mode and version. + * @param mode + * @param version + * @return the size of the appropriate length indicator (bits). + */ +extern int MQRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode + * @param version + * @return the maximum length (bytes) + */ +extern int MQRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version + * @return BCH encoded version information pattern + */ +extern unsigned int MQRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask + * @param version + * @param level + * @return BCH encoded format information pattern + */ +extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * When the same version is requested twice or more, a copy of cached frame + * is returned. + * @param version + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *MQRspec_newFrame(int version); + +/** + * Clear the frame cache. Typically for debug. + */ +extern void MQRspec_clearCache(void); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107. + */ +#define MQRSPEC_MODEID_NUM 0 +#define MQRSPEC_MODEID_AN 1 +#define MQRSPEC_MODEID_8 2 +#define MQRSPEC_MODEID_KANJI 3 +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __MQRSPEC_H__ */ diff --git a/code/application/source/sf_app/code/include/qrenc.h b/code/application/source/sf_app/code/include/qrenc.h new file mode 100755 index 000000000..4ecab822f --- /dev/null +++ b/code/application/source/sf_app/code/include/qrenc.h @@ -0,0 +1,44 @@ +/** + * qrencode - QR Code encoder + * + * QR Code encoding tool + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +//#include "getopt.h" +//#include "jpeglib.h" + +#include "qrencode.h" + +#define INCHES_PER_METER (100.0/2.54) + +QRcode *encode(const unsigned char *intext, int length); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/code/application/source/sf_app/code/include/qrencode.h b/code/application/source/sf_app/code/include/qrencode.h new file mode 100755 index 000000000..a2d8372e2 --- /dev/null +++ b/code/application/source/sf_app/code/include/qrencode.h @@ -0,0 +1,415 @@ +/** + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute · it and/or + * modify޸ it under the terms ofʲôʲô the GNU Lesser General Public + * License (GNUȨ)as published (棬)by the Free Software Foundation(); either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** \mainpage + * Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D + * symbology. LibqrencodeQRŵıݣһ2DŵĿ + * + * \section encoding Encoding ֱı + * + * There are two ways to encode data:ַʽ encoding a string Ϊַб or + * encoding a structured dataΪݽб. + * + * \subsection encoding-string Encoding a string encoding-stringһΪַб + * You can encode a string by calling QRcode_encodeString().ͨQRcode_encodeString()Ϊַб + * The given string is parsed automatically and encoded.ַԶͱ If you want to encode + * data that can be represented as a C string style (NUL terminated ֹ), you can + * simply use this way. + * + * If the input data contains Kanji (Shift-JIS) characters and you want to + * encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.ʾʾ + * Otherwise, all of non-alphanumeric ĸַ characters are encoded as 8 bit data. + * If you want to encode a whole string in 8 bit mode, use + * QRcode_encodeString8bit() instead. + * + * Please note that a C string can not contain NUL character. If your data + * contains NUL, you should chose the second way. ע⣬CַܰNULLַаNULӦѡڶַʽ + * + * \subsection encoding-input Encoding a structured data encoding-inputһΪݽб + * You can construct a structured input data manually. ֶһṹݡIf the structure of the + * input data is known, you can use this way. + * At first, create a ::QRinput object by QRinput_new(). Then add input data + * to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput() + * to encode the QRinput data. + * You can reuse the QRinput data again to encode it in other symbols with + * different parameters.ͬ + * + * \section result Result + * The encoded symbol is resulted as a ::QRcode object. It will contain + * its version number汾, width of the symbolŵĿ and an array represents the symbol ʾ. + * See ::QRcode for the details. You can free the object by QRcode_free(). + * + * Please note that the version of the result may be larger than specified. + * In such cases, the input data would be too large to be encoded in a + * symbol of the specified version.ݻΪָ̫汾ķ + * + * \section structured Structured append + * Libqrencode can generate "Structured-appended" symbols that enables to split + * a large data set into mulitple QR codes.һܴݷֳɶQRcode A QR code reader concatenates + * multiple QR code symbols into a string.QRĶӶQRתַ + * Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured() + * to generate structured-appended symbols. This functions returns an instance + * of ::QRcode_List. The returned list is a singly-linked list of QRcode: you + * can retrieve each QR code in this way: + * + * \code + * QRcode_List *qrcodes; + * QRcode_List *entry; + * QRcode *qrcode; + * + * qrcodes = QRcode_encodeStringStructured(...); + * entry = qrcodes; + * while(entry != NULL) { + * qrcode = entry->code; + * // do something + * entry = entry->next; + * } + * QRcode_List_free(entry); + * \endcode + * + * Instead of using auto-parsing functions, you can construct your own + * structured input. At first, instantiate an object of ::QRinput_Struct + * by calling QRinput_Struct_new(). This object can hold multiple ::QRinput, + * and one QR code is generated for a ::QRinput. + * QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct + * object. In order to generate structured-appended symbols, it is required to + * embed headers to each symbol. You can use + * QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate + * headers to each symbol. You should call this function just once before + * encoding symbols. + *ԹԼinputṹȡԶȣQRinput_Struct_new()ʵһQRinput_Struct + *ԱQRinputQRinput_Struct_appendInput()һQRinputQRinput_StructС + *Ϊstructured-appendedţҪǶͷÿСʹQRinput_Struct_insertStructuredAppendHeaders()ʵͷÿС + *ڱǮһΡ + */ + +#ifndef __QRENCODE_H__ +#define __QRENCODE_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +/** + * Encoding mode. + */ +typedef enum { + QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only + QR_MODE_NUM = 0, ///< Numeric mode ģʽ + QR_MODE_AN, ///< Alphabet-numeric mode ĸģʽ + QR_MODE_8, ///< 8-bit data mode 8λģʽ + QR_MODE_KANJI, ///< Kanji (shift-jis) mode ģʽ + QR_MODE_STRUCTURE, ///< Internal use only + QR_MODE_ECI, ///< ECI mode + QR_MODE_FNC1FIRST, ///< FNC1, first position + QR_MODE_FNC1SECOND, ///< FNC1, second position +} QRencodeMode; + +/** + * Level of error correction. + */ +typedef enum { + QR_ECLEVEL_L = 0, ///< lowest + QR_ECLEVEL_M, + QR_ECLEVEL_Q, + QR_ECLEVEL_H ///< highest +} QRecLevel; + +/** + * Maximum version (size) of QR-code symbol. + */ +#define QRSPEC_VERSION_MAX 40 + +/** + * Maximum version (size) of QR-code symbol. + */ +#define MQRSPEC_VERSION_MAX 4 + + +/****************************************************************************** + * Input data (qrinput.c) + *****************************************************************************/ + +/** + * Singly linked list to contain input strings. An instance of this class + * contains its version and error correction level too. It is required to + * set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(), + * or use QRinput_new2() to instantiate an object. + */ +typedef struct _QRinput QRinput; + +/** + * Instantiate an input data object.ʵһݶ The version is set to 0 (auto-select) + * and the error correction level is set to QR_ECLEVEL_L. + * @return an input object (initialized)һʵ. On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput *QRinput_new(void); + +/** + * Instantiate an input data object. + * @param version version number. + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_new2(int version, QRecLevel level); + +/** + * Instantiate an input data object. Object's Micro QR Code (һֶά,ֻһλΣ洢ȽСڴӡռС)flag is set. + * Unlike with full-sized QR Code, version number must be specified (>0). + * @param version version number (1--4). + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_newMQR(int version, QRecLevel level); + +/** + * Append data to an input object. + * The data is copied and appended to the input object. + * @param input input object. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data); + +/** + * Append ECI header.ַ + * @param input input object. + * @param ecinum ECI indicator number (0 - 999999) + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum); + +/** + * Get current version. + * @param input input object. + * @return current version. + */ +extern int QRinput_getVersion(QRinput *input); + +/** + * Set version of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code.ð汾ŲMicro QR Code + * @param input input object. + * @param version version number (0 = auto) + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersion(QRinput *input, int version); + +/** + * Get current error correction level. + * @param input input object. + * @return Current error correcntion level. + */ +extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input); + +/** + * Set error correction level of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code. + * @param input input object. + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level); + +/** + *ڸMicro QR Code ð汾ź; + * Set version and error correction level of the QR code at once. + * This function is recommened for Micro QR Code. + * @param input input object. + * @param version version number (0 = auto) + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level); + +/** + * Free the input object. + * All of data chunks in the input object are freed too. + * @param input input object. + */ +extern void QRinput_free(QRinput *input); + +/** + * Validate the input data. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 invalid arguments. + */ +extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data); + + +/** + * Free all of QRinput in the set. + * @param s a structured input object. + */ + + +/****************************************************************************** + * QRcode output (qrencode.c) + *****************************************************************************/ + +/** + * QRcode class. + * Symbol data is represented as an array contains width*width uchars. + * Each uchar represents a module (dot). If the less significant bitλ of + * the uchar is 1, the corresponding module is black. The other bits are + * meaningless for usual applications, but here its specification is described. + * + *
+ * MSB 76543210 LSB
+ *     |||||||`- 1=black/0=white
+ *     ||||||`-- data and ecc code area
+ *     |||||`--- format information
+ *     ||||`---- version information
+ *     |||`----- timing pattern
+ *     ||`------ alignment pattern
+ *     |`------- finder pattern and separator
+ *     `-------- non-data modules (format, timing, etc.)
+ * 
+ */ +typedef struct { + int version; ///< version of the symbol + int width; ///< width of the symbol + unsigned char *data; ///< symbol data +} QRcode; + +/** + * Singly-linked list of QRcode. Used to represent a structured symbols. + * A list is terminated with NULL. + */ +typedef struct _QRcode_List QRcode_List; + +struct _QRcode_List { + QRcode *code; + QRcode_List *next; +}; + +/** + * Create a symbol from the input data. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param input input data. + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode *QRcode_encodeInput(QRinput *input); + +/** + * Create a symbol from the string. The library automatically parses the input + * string and encodes in a QR Code symbol.ַͨһţַԶַȻΪб롣 + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param string input string. It must be NUL terminated. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @param hint tell the library how non-alphanumerical characters should be + * encoded. If QR_MODE_KANJI is given, kanji characters will be + * encoded as Shif-JIS characters. If QR_MODE_8 is given, all of + * non-alphanumerical characters will be encoded as is. If you want + * to embed UTF-8 string, choose this. + * @param casesensitive case-sensitive(1) or not(0). + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Same to QRcode_encodeString(), but encode whole data in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ + + +/** + * Micro QR Code version of QRcode_encodeString(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Encode byte stream (may include '\0') in 8-bit mode.8λģʽ¶ֽб + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param size size of the input data. + * @param data input data. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Micro QR Code version of QRcode_encodeData(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Free the instance of QRcode class. + * @param qrcode an instance of QRcode class. + */ +extern void QRcode_free(QRcode *qrcode); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + +#endif /* __QRENCODE_H__ */ diff --git a/code/application/source/sf_app/code/include/qrencode_inner.h b/code/application/source/sf_app/code/include/qrencode_inner.h new file mode 100755 index 000000000..8dc95f4d0 --- /dev/null +++ b/code/application/source/sf_app/code/include/qrencode_inner.h @@ -0,0 +1,97 @@ +/** + * qrencode - QR Code encoder + * + * Header for test use + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRENCODE_INNER_H__ +#define __QRENCODE_INNER_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * This header file includes definitions for test use. + */ + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + unsigned char *data; + int eccLength; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +extern QRRawCode *QRraw_new(QRinput *input); +extern unsigned char QRraw_getCode(QRRawCode *raw); +extern void QRraw_free(QRRawCode *raw); + +/****************************************************************************** + * Raw code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +extern MQRRawCode *MQRraw_new(QRinput *input); +extern unsigned char MQRraw_getCode(MQRRawCode *raw); +extern void MQRraw_free(MQRRawCode *raw); + +/****************************************************************************** + * Frame filling + *****************************************************************************/ + + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ +extern QRcode *QRcode_encodeMask(QRinput *input, int mask); +extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask); +extern QRcode *QRcode_new(int version, int width, unsigned char *data); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __QRENCODE_INNER_H__ */ diff --git a/code/application/source/sf_app/code/include/qrinput.h b/code/application/source/sf_app/code/include/qrinput.h new file mode 100755 index 000000000..8a73402ea --- /dev/null +++ b/code/application/source/sf_app/code/include/qrinput.h @@ -0,0 +1,132 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRINPUT_H__ +#define __QRINPUT_H__ + +#include "qrencode.h" +#include "bitstream.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int QRinput_isSplittableMode(QRencodeMode mode); + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ +typedef struct _QRinput_List QRinput_List; + +struct _QRinput_List { + QRencodeMode mode; + int size; ///< Size of data chunk (byte). + unsigned char *data; ///< Data chunk. + BitStream *bstream; + QRinput_List *next; +}; + +/****************************************************************************** + * Input Data + *****************************************************************************/ +struct _QRinput { + int version; + QRecLevel level; + QRinput_List *head; + QRinput_List *tail; + int mqr; + int fnc1; + unsigned char appid; +}; + +/****************************************************************************** + * Structured append input data + *****************************************************************************/ +typedef struct _QRinput_InputList QRinput_InputList; + +struct _QRinput_InputList { + QRinput *input; + QRinput_InputList *next; +}; + +struct _QRinput_Struct { + int size; ///< number of structured symbols + int parity; + QRinput_InputList *head; + QRinput_InputList *tail; +}; + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ +extern unsigned char *QRinput_getByteStream(QRinput *input); + + +extern int QRinput_estimateBitsModeNum(int size); +extern int QRinput_estimateBitsModeAn(int size); +extern int QRinput_estimateBitsMode8(int size); +extern int QRinput_estimateBitsModeKanji(int size); + +extern QRinput *QRinput_dup(QRinput *input); + +extern const signed char QRinput_anTable[128]; + +/** + * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). + * @param __c__ character + * @return value + */ +#define QRinput_lookAnTable(__c__) \ + ((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__]) + +/** + * Length of a standard mode indicator in bits. + */ + +#define MODE_INDICATOR_SIZE 4 + +/** + * Length of a segment of structured-append header. + */ +#define STRUCTURE_HEADER_SIZE 20 + +/** + * Maximum number of symbols in a set of structured-appended symbols. + */ +#define MAX_STRUCTURED_SYMBOLS 16 + +#ifdef WITH_TESTS +extern BitStream *QRinput_mergeBitStream(QRinput *input); +extern BitStream *QRinput_getBitStream(QRinput *input); +extern int QRinput_estimateBitStreamSize(QRinput *input, int version); +extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits); +extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __QRINPUT_H__ */ diff --git a/code/application/source/sf_app/code/include/qrspec.h b/code/application/source/sf_app/code/include/qrspec.h new file mode 100755 index 000000000..78d9deb46 --- /dev/null +++ b/code/application/source/sf_app/code/include/qrspec.h @@ -0,0 +1,190 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRSPEC_H__ +#define __QRSPEC_H__ + +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define QRSPEC_WIDTH_MAX 177 + +/** + * Return maximum data code length (bytes) for the version. + * @param version + * @param level + * @return maximum size (bytes) + */ +extern int QRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version + * @param level + * @return ECC size (bytes) + */ +extern int QRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level + * @return version number + */ +extern int QRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version + * @return width + */ +extern int QRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version + * @return number of remainder bits + */ +extern int QRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of lenght indicator for the mode and version. + * @param mode + * @param version + * @return the size of the appropriate length indicator (bits). + */ +extern int QRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode + * @param version + * @return the maximum length (bytes) + */ +extern int QRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Return an array of ECC specification. + * @param version + * @param level + * @param spec an array of ECC specification contains as following: + * {# of type1 blocks, # of data code, # of ecc code, + * # of type2 blocks, # of data code} + */ +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]); + +#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3]) +#define QRspec_rsBlockNum1(__spec__) (__spec__[0]) +#define QRspec_rsDataCodes1(__spec__) (__spec__[1]) +#define QRspec_rsEccCodes1(__spec__) (__spec__[2]) +#define QRspec_rsBlockNum2(__spec__) (__spec__[3]) +#define QRspec_rsDataCodes2(__spec__) (__spec__[4]) +#define QRspec_rsEccCodes2(__spec__) (__spec__[2]) + +#define QRspec_rsDataLength(__spec__) \ + ((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \ + (QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__))) +#define QRspec_rsEccLength(__spec__) \ + (QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__)) + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version + * @return BCH encoded version information pattern + */ +extern unsigned int QRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask + * @param level + * @return BCH encoded format information pattern + */ +extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * When the same version is requested twice or more, a copy of cached frame + * is returned. + * @param version + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *QRspec_newFrame(int version); + +/** + * Clear the frame cache. Typically for debug. + */ +extern void QRspec_clearCache(void); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 of JIS X0510:2004, pp.16. + */ +#define QRSPEC_MODEID_ECI 7 +#define QRSPEC_MODEID_NUM 1 +#define QRSPEC_MODEID_AN 2 +#define QRSPEC_MODEID_8 4 +#define QRSPEC_MODEID_KANJI 8 +#define QRSPEC_MODEID_FNC1FIRST 5 +#define QRSPEC_MODEID_FNC1SECOND 9 +#define QRSPEC_MODEID_STRUCTURE 3 +#define QRSPEC_MODEID_TERMINATOR 0 + #ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif /* __QRSPEC_H__ */ diff --git a/code/application/source/sf_app/code/include/rscode.h b/code/application/source/sf_app/code/include/rscode.h new file mode 100755 index 000000000..09a243d2c --- /dev/null +++ b/code/application/source/sf_app/code/include/rscode.h @@ -0,0 +1,51 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon encoder. This code is taken from Phil Karn's libfec then + * editted and packed into a pair of .c and .h files. + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __RSCODE_H__ +#define __RSCODE_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* + * General purpose RS codec, 8-bit symbols. + */ + +typedef struct _RS RS; + +extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad); +extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity); +extern void free_rs_char(RS *rs); +extern void free_rs_cache(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __RSCODE_H__ */ diff --git a/code/application/source/sf_app/code/include/sf_aes.h b/code/application/source/sf_app/code/include/sf_aes.h new file mode 100755 index 000000000..8b2125c8a --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_aes.h @@ -0,0 +1,34 @@ +#ifndef __SF_AES_H +#define __SF_AES_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_type.h" + + +//UINT32 sf_cipher(UINT32 aesType,UINT8 operation,UINT8 *input,UINT8 *output); +UINT32 sf_cipher(UINT32 aesType,UINT8 operation,UINT8 *input,UINT8 *output, UINT8 srcl); + + + +extern void sf_cipher_test(void); +extern void sf_cipher_test1(void); + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + + + + + + diff --git a/code/lib/source/sifar/code/include/sf_base64.h b/code/application/source/sf_app/code/include/sf_base64.h similarity index 100% rename from code/lib/source/sifar/code/include/sf_base64.h rename to code/application/source/sf_app/code/include/sf_base64.h diff --git a/code/application/source/sf_app/code/include/sf_bmp.h b/code/application/source/sf_app/code/include/sf_bmp.h new file mode 100755 index 000000000..651832030 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_bmp.h @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * Ver: 1.0.0 2021.04.15 + * Description: creat +**************************************************************************/ +#ifndef _SF_BMP_H_ +#define _SF_BMP_H_ +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct sfBMP_DATA_S +{ + int width; //width of the symbol + int height; //height of the symbol + unsigned char *data; //symbol data + +} SF_BMP_DATA_S; + + +int sf_qrcode_bmpfile_write(QRcode *DataInfo, const char *outfile, int magnification); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + diff --git a/code/application/source/sf_app/code/include/sf_commMng.h b/code/application/source/sf_app/code/include/sf_commMng.h new file mode 100755 index 000000000..801112396 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_commMng.h @@ -0,0 +1,39 @@ +#ifndef __SF_COMMMNG_H__ +#define __SF_COMMMNG_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_type.h" +#include "sf_param_common.h" + + + +SINT32 sf_sem_init(SF_CHAR *pathname,SINT32 *psemid); + +SINT32 sf_sem_down(SINT32 semid, SINT32 who); + +SINT32 sf_sem_up(SINT32 semid, SINT32 who); + +SINT32 sf_sem_deinit(SINT32 semid); + +SINT32 sf_share_mem_file_init(void); + +SINT32 sf_share_mem_file_deinit(void); + +SINT32 sf_share_mem_customer_init(void); + +SINT32 sf_share_mem_customer_deinit(void); + + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + diff --git a/code/application/source/sf_app/code/include/sf_commu_mcu.h b/code/application/source/sf_app/code/include/sf_commu_mcu.h new file mode 100755 index 000000000..3b1467c75 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_commu_mcu.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: ljy + * Ver: 1.0.0 2022.06.15 + * Description: creat +**************************************************************************/ + +#ifndef __SF_COMMU_MCU_H +#define __SF_COMMU_MCU_H + +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus +#include + +#define SERIAL_DEVICE_PATH "/dev/ttyS2" +#define BUF_REG_SIZE (REG_SIZE*2+8) + +typedef struct { + unsigned char buf[BUF_REG_SIZE]; + unsigned int index; +}SMAPBUF_t; + + +void mcubuf_reset(void); +int sf_commu_mcu_interface_init(int speed, char flow_ctrl, int databits, int stopbits, char parity); +int sf_commu_mcu_open(void); +int sf_commu_mcu_close(void); +int sf_commu_write(unsigned char * buf, int len); +int sf_commu_read(unsigned char * buf, int len); +int sf_set_mcu_reg(unsigned char reg, unsigned char val); +int sf_get_mcu_reg(unsigned char reg); +unsigned int sf_set_mcu_reg_ack_depack(unsigned int * address, unsigned int * value); +unsigned int sf_get_mcu_reg_ack_depack(unsigned int * address, unsigned int * value); +int sf_commu_wait(unsigned char cmd); +void sf_commu_reset(void); +int sf_commu_set_mcu(unsigned char reg, unsigned char val); +int sf_commu_get_mcu(unsigned char reg); +int sf_getRegFromMcu_depack(unsigned char * dataToParse, unsigned int datalen, unsigned char * regAddr, unsigned char * regVal); +int sf_getRegFromMcu_ack(unsigned char regAddr, unsigned char regVal); +unsigned char sf_commu_parse_mcu_data(unsigned char * src, unsigned int len); +void sf_commu_mcu_task_start(void); +void sf_commu_mcu_task_stop(void); +unsigned char sf_commu_mcu_task_running(void); +unsigned int sf_get_mcu_reg_ack_depack_many(unsigned char reg[], unsigned char val[], unsigned int * num); +int sf_set_mcu_reg_many(unsigned char reg[], unsigned char val[], unsigned int num); +int sf_get_mcu_reg_many(unsigned char reg[], unsigned int num); +int sf_commu_set_mcu_many(unsigned char reg[], unsigned char val[], unsigned int *num); +int sf_commu_get_mcu_many(unsigned char reg[], unsigned char val[], unsigned int *num); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +#endif diff --git a/code/application/source/sf_app/code/include/sf_commu_mcu_reg.h b/code/application/source/sf_app/code/include/sf_commu_mcu_reg.h new file mode 100755 index 000000000..2475ee3ea --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_commu_mcu_reg.h @@ -0,0 +1,349 @@ +#ifndef __SF_COMMU_MCU_REG_H +#define __SF_COMMU_MCU_REG_H + +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: oliver + * Ver: 1.0.0 2019.06.06 + * Description: +**************************************************************************/ +#ifndef _SF_MCU_H_ +#define _SF_MCU_H_ + +#include "sf_type.h" +#include "sf_param_common.h" + + +#define DIGITAL_PIR 1 + +#define REG_SIZE 91 + +#define SF_MCU_NIGHT_MODE_LUMINANCE 380 + +/*REG POWER_OFFON*/ +#define MCU_MODE_AUTO 0x00 +#define MCU_MODE_OFF 0x40 +#define MCU_MODE_SETUP 0x80 + +#define PWR_OFF 0x00 +#define PWR_ON_SETUP 0x01 +#define PWR_ON_TIMELAPSE 0x02 +#define PWR_ON_AUTO 0x03 +#define PWR_ON_SMS 0x04 +#define PWR_ON_PIR 0x05 +#define PWR_ON_LBAT 0x06 +#define PWR_ON_SERVER 0x07 +#define PWR_ON_DAILY_REPORT 0x08 +#define PWR_ON_USB 0x09 +#define PWR_ON_GPRS_INIT 0x0A +#define PWR_ON_TIME_SYNC 0x0B +#define PWR_ON_TIME_SEND 0x0C + +/*REG FUNCTION_SWTICH*/ +#define PIR_OFF 0x00 +#define PIR_ON 0x01 +#define TIMELAPSE_ON 0x02 +#define PIR_DELAY_ON 0x04 +#define TIME_SYNC_ON 0x08 +#define DAILY_REPORT_ON 0x10 +#define DAILY_SEND1_ON 0x20 +#define DAILY_SEND2_ON 0x40 +#define GPS_ALWAYS_ON 0x80 + +/*REG FUNCTION_SWTICH1*/ +#define DAILY_SEND3_ON 0x01 +#define DAILY_SEND4_ON 0x02 + +/*REG FUNCTION_SWTICH2*/ +#define WDT_OFF 0x01 +#define DEBUG_MODE_ON 0x02 + +/*REG GPS_POWER_TIMER_CLEAR */ +#define GPS_COUNTDOWM_RESET 0x01 + +/*REG GPS_POWER_CTRL */ +#define GPS_PWR_ON 0x01 + +/*REG PIR_SENSITIVITY*/ +#define DIGITAL_PIR_SENSITIVITY_MASK 0xFF +#define GPRS_ON 0x80 +#define GPRS_MODE_MASK 0x60 +#define GPRS_DAILY 0x00 +#define GPRS_INSTANT 0x40 +#define GPRS_HYBRID 0x20 +#define TIME_SYNC_RESET 0x10 +#define PIR_SEN_HIGH 0x00 +#define PIR_SEN_MIDDLE 0x01 +#define PIR_SEN_LOW 0x02 + +/*REG DSP_BUSY*/ +#define DSP_BUSY 0x01 +#define DSP_IDLE 0x00 + +/*REG SYS_STATUS*/ +#define SYS_SD_INSERT 0x01 +#define SYS_MENORY_FULL 0x02 +#define SYS_USB_INSERT 0x04 +#define SYS_SOFT_UPDATE 0x08 +#define GPRS_RESTART 0x10 +#define POWER_CYCLE 0x20 +#define SYS_CAM_OFF 0x40 +#define PIR_RESTART 0x80 + +/*REG POWEROFF_TYPE*/ +#define PWROFF_NOUSE 0x00 +#define PWROFF_GPRS_INIT 0x01 +#define PWROFF_SMS_RESTART 0x02 +#define PWROFF_LBAT 0x40 +#define PWROFF_TIMEOUT 0x80 + +typedef enum +{ + MCU_SUB_VER = 0, + MCU_VER_L = 1, + MCU_VER_H = 2, + MCU_PRODUCT_INFO = 3, + START_MODE = 4, + LUMINANCE_L = 5, + LUMINANCE_H = 6, + RESERVER1 = 7, + + SF_RTC_YEAR = 8, + SF_RTC_MONTH = 9, + SF_RTC_DAY = 10, + SF_RTC_HOUR = 11, + SF_RTC_MINUTE = 12, + SF_RTC_SEC = 13, + SF_RTC_WEEK = 14, + FUNCTION_SWTICH0 = 15, + FUNCTION_SWTICH1 = 16, + FUNCTION_SWTICH2 = 17, + RESERVER2 = 18, + + GPS_POWER_TIMER_CLEAR = 19, + GPS_POWER_CTRL = 20, + ANALOG_PIR_SENSITIVITY = 21, + DIGITAL_PIR_SENSITIVITY= 22, + DIGITAL_PIR_CFG = 23, + DSP_BUSY_STATUS = 24, + SYS_STATUS = 25, + RESERVER3 = 26, + + POWEROFF_TYPE = 27, + WDT_TIME = 28, + VBAT_LOW_WARN_VAL = 29, + VBAT_RECOVER_VAL = 30, + RESERVER4 = 31, + + TIMELAPSE_HOUR = 32, + TIMELAPSE_MINUTE = 33, + TIMELAPSE_SEC = 34, + PIR_DELAY_HOUR = 35, + PIR_DELAY_MINUTE = 36, + PIR_DELAY_SEC = 37, + TIME_SYNC_HOUR = 38, + TIME_SYNC_MINUTE = 39, + TIME_SYNC_SEC = 40, + DAILY_REPORT_HOUR = 41, + DAILY_REPORT_MINUTE = 42, + DAILY_SEND1_HOUR = 43, + DAILY_SEND1_MINUTE = 44, + DAILY_SEND2_HOUR = 45, + DAILY_SEND2_MINUTE = 46, + DAILY_SEND3_HOUR = 47, + DAILY_SEND3_MINUTE = 48, + DAILY_SEND4_HOUR = 49, + DAILY_SEND4_MINUTE = 50, + RESERVER5 = 51, + RESERVER6 = 52, + RESERVER7 = 53, + + WORKTIME1_SWITCH = 54, + WORKTIME1_START_HOUR = 55, + WORKTIME1_START_MINUTE = 56, + WORKTIME1_STOP_HOUR = 57, + WORKTIME1_STOP_MINUTE = 58, + + WORKTIME2_SWITCH = 59, + WORKTIME2_START_HOUR = 60, + WORKTIME2_START_MINUTE = 61, + WORKTIME2_STOP_HOUR = 62, + WORKTIME2_STOP_MINUTE = 63, + + WORKTIME3_SWITCH = 64, + WORKTIME3_START_HOUR = 65, + WORKTIME3_START_MINUTE = 66, + WORKTIME3_STOP_HOUR = 67, + WORKTIME3_STOP_MINUTE = 68, + + WORKTIME4_SWITCH = 69, + WORKTIME4_START_HOUR = 70, + WORKTIME4_START_MINUTE = 71, + WORKTIME4_STOP_HOUR = 72, + WORKTIME4_STOP_MINUTE = 73, + + WORKTIME5_SWITCH = 74, + WORKTIME5_START_HOUR = 75, + WORKTIME5_START_MINUTE = 76, + WORKTIME5_STOP_HOUR = 77, + WORKTIME5_STOP_MINUTE = 78, + + WORKTIME6_SWITCH = 79, + WORKTIME6_START_HOUR = 80, + WORKTIME6_START_MINUTE = 81, + WORKTIME6_STOP_HOUR = 82, + WORKTIME6_STOP_MINUTE = 83, + + DSP_WRITE_FLG = 84, + + RESERVER8 = 85, + RESERVER9 = 86, + RESERVER10 = 87, + RESERVER11 = 88, + RESERVER12 = 89, + RESERVER13 = 90, +}PARA_REG; + + + +typedef enum { + POWEROFF_COUNTDOWN = 1, + POWEROFF_PVDOWN, + POWEROFF_KEYDOWN, + POWEROFF_KEYREBOOT, + POWEROFF_GPRSREBOOT, + POWEROFF_KEYOFF +}POWEROFF_MODE; + + +typedef enum { + SF_MCU_STARTMODE = 0, + SF_MCU_POWERON, + SF_MCU_POWEROFF, + SF_MCU_CTRL_MODULE_PIR, + SF_MCU_PARA, + SF_MCU_RESET_MODULE, + SF_MCU_SOFT_UPDATE, + SF_MCU_POWER_RESTART, + SF_MCU_PIR_RESTART, + SF_MCU_TEST_PIR, + SF_MCU_PARAM_MAX +} MCUParam_t; + + +typedef enum { + TRIG_MOTION = 1, + TRIG_TIMELAPSE, + TRIG_SETUP, + TRIG_COMMOND, +}TRIG_TYPE; + + +typedef enum { + WORKING_TIME_0 = 0, + WORKING_TIME_1, + WORKING_TIME_2, + WORKING_TIME_3, + WORKING_TIME_4, + WORKING_TIME_5, + WORKING_TIME_ALL = 0xff, +}WORKING_TIME_TYPE; +#if 0 +typedef enum sfMCU_STARTUP_TYPE_E +{ + SF_MCU_STARTUP_OFF = 0x00,/* POWER OFF*/ + SF_MCU_STARTUP_ONKEY = 0x01,/*key on SETUP*/ + SF_MCU_STARTUP_TIMELAPSE = 0x02,/*timelapse power on*/ + SF_MCU_STARTUP_NORMAL = 0x03,/*Dial the key to ON*/ + SF_MCU_STARTUP_RING = 0x04,/*ring power on*/ + SF_MCU_STARTUP_PIR = 0x05,/*pir power on*/ + SF_MCU_STARTUP_WARNING = 0x06,/*low bat worning power on*/ + SF_MCU_STARTUP_SERVER = 0x07,/*server power on(reserve)*/ + SF_MCU_STARTUP_DP = 0x08,/*DailyReport power on*/ + SF_MCU_STARTUP_USB = 0x09,/*USB power on*/ + SF_MCU_STARTUP_RESET = 0x0A,/*power on to reset(reserve)*/ + SF_MCU_STARTUP_SYN_PARAM = 0x0B,/*power on to syn param(reserve)*/ + SF_MCU_STARTUP_BATCH_SEND= 0x0C,/*power on to send batch*/ + SF_MCU_STARTUP_BUTT = 0X0D, +} SF_STARTUP_TYPE_E; + +typedef enum sfPOWEROFF_TYPE_E +{ + SF_POWEROFF_NORMAL = 0x00, + SF_POWEROFF_AUTO = 0x01, /*auto power when 3min no operation*/ + SF_POWEROFF_REBOOT = 0x02, /*poweroff to reboot*/ + SF_POWEROFF_KEYON = 0x03, + SF_POWEROFF_KEYOFF = 0x04, + SF_POWEROFF_SYNC_PARAM = 0x05, + SF_POWEROFF_GPS_DP = 0x06, + SF_POWEROFF_SD_FULL = 0x07, + SF_POWEROFF_LOW_BAT = 0x08, + SF_POWEROFF_NO_SD = 0x09, + SF_POWEROFF_BUTT, +} SF_POWEROFF_TYPE_E; +#endif +typedef struct sf_TIME_S { + unsigned short Year; /* Year > 1970*/ + unsigned short Mon; /* Mon range[1-12]*/ + unsigned short Day; /*Day range[1-31]*/ + unsigned short Hour; /*Hour range[0-23]*/ + unsigned short Min; /*Min range[0-59]*/ + unsigned short Sec; /*Sec range[0-59]*/ +} SF_TIME_S; + +unsigned char sf_mcu_power_on_para_get (MCUParam_t attrId); +unsigned char sf_mcu_wdg_set(unsigned char value); +void sf_mcu_poweron_4g_module(void); +unsigned char sf_mcu_start_mode_get(void); + +SF_BOOL sf_is_night_mode(unsigned int isRefresh); +unsigned char sf_mcu_rtc_get (SF_TIME_S *time); +unsigned char sf_mcu_reg_set(MCUParam_t attrId, unsigned char val); +void sf_set_mcu_sub_ver(unsigned char mcuSubVersion); +void sf_set_mcu_ver(unsigned short mcuVersion); +unsigned short sf_get_light_value(void); +unsigned char sf_get_mcu_sub_ver(void); +unsigned short sf_get_mcu_ver(void); + +int sf_get_ae_shutter(void); +int sf_get_ae_sensor_gain(void); + + +int sf_set_ae_shutter(unsigned int value); + +int sf_set_ae_sensor_gain(unsigned int value); + + +int sf_set_cur_light_val(unsigned int value); + +int sf_get_last_light_val(void); +SF_TIME_S sf_get_mcu_poweroff_date(void); +void sf_set_mcu_poweroff_date(SF_PARA_TIME_S date); + + +extern unsigned char PowerOnMode; +extern unsigned short TrigType; + + +#endif + + + + +#endif + + + diff --git a/code/application/source/sf_app/code/include/sf_dataMng.h b/code/application/source/sf_app/code/include/sf_dataMng.h new file mode 100755 index 000000000..b63c7c95a --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_dataMng.h @@ -0,0 +1,90 @@ + +#ifndef __SF_DATA_PROC_H__ +#define __SF_DATA_PROC_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_type.h" +#include "sf_param_common.h" + + +typedef enum SF_CMD_QUERYPENDING_E { + + SF_CMD_QUERYPENDING_GETCFGFILE = 0X2000, + SF_CMD_QUERYPENDING_GETPICTURE = 0X2002, + SF_CMD_QUERYPENDING_GETSTATUS = 0X2004, + SF_CMD_QUERYPENDING_GETSLEEPTIME = 0X2006, + SF_CMD_QUERYPENDING_REBOOT = 0X2008, + SF_CMD_QUERYPENDING_SETSYSTEMTIME = 0X200A, + SF_CMD_QUERYPENDING_SETCAMERAMODE = 0X200C, + SF_CMD_QUERYPENDING_SETWORKMODE = 0X200E, + SF_CMD_QUERYPENDING_SETOTHER = 0X2010, + SF_CMD_QUERYPENDING_SETSERVER = 0X2012, + SF_CMD_QUERYPENDING_UPLOADCFGFILE = 0X2014, + SF_CMD_QUERYPENDING_GETCAMERAMODE = 0X2016, + SF_CMD_QUERYPENDING_GETMODECFG = 0X2018, + SF_CMD_QUERYPENDING_GETOTHERCFG = 0X201A, + SF_CMD_QUERYPENDING_GETSERVERPAREAM = 0X201C, + SF_CMD_QUERYPENDING_SETUPLOADPICSIZE = 0X201E, + SF_CMD_QUERYPENDING_GETUPLOADPICSIZE = 0X2020, + SF_CMD_QUERYPENDING_SYNPARAM = 0X2022, + SF_CMD_QUERYPENDING_VERSIONUPDATE = 0X2024, + SF_CMD_QUERYPENDING_GETGPSINFO = 0X2026, + SF_CMD_QUERYPENDING_SETGPSANTITHIEF = 0X2028, + + SF_QUERYPENDING_COMMAND_RESET = 0X202A, + SF_QUERYPENDING_COMMAND_GETPICFLAG = 0X202C, + SF_QUERYPENDING_COMMAND_FORMAT = 0X202E, + SF_QUERYPENDING_COMMAND_BUTT = 0X2030, + + + }SF_CMD_QUERYPENDING_E; +UINT16 crcCheck( UINT8 strContent[],UINT16 usDataLen,UINT16 crc); +UINT16 makeCrc(UINT8 strContent[], UINT16 len); + + void sf_data_subscribe_result_set(UINT16 ret); + + UINT8 sf_data_has_command_get(void); + + UINT8 sf_data_transfer_mode_get(void); + + SINT32 sf_data_cam_local_time_get(SF_PARA_TIME_S* pstdata); + + UINT32 sf_data_pendingcmd_get(void); + + +SINT32 sf_data_grouping_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); +SINT32 sf_data_grouping_fileresult(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam,SF_VOID *pstfileAttr); + +SINT32 sf_data_grouping_disconnection(SF_DATA_ATTR_S *pstdata,SF_VOID *Param); +SINT32 sf_data_grouping_query_cmd(SF_DATA_ATTR_S *pstdata); +SINT32 sf_data_grouping_query_cmd_param(SF_DATA_ATTR_S *pstdata); +SINT32 sf_data_grouping_cmd_report(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam, SF_FILE_ATTR_S *pstfileAttr); +SINT32 sf_data_grouping_get_bind_account(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); +SINT32 sf_data_grouping_sync_cfg(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_data_analysis_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); +SINT32 sf_data_analysis_fileresult(SF_DATA_ATTR_S *param); +SINT32 sf_data_analysis_query_cmd(SF_DATA_ATTR_S *param); +SINT32 sf_data_analysis_query_cmd_param(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); +SINT32 sf_data_analysis_cmd_report(SF_DATA_ATTR_S *param); +SINT32 sf_data_analysis_bind_account(SF_DATA_ATTR_S *pstdata,SF_FN_PARAM_S *pfnParam); +SINT32 sf_data_analysis_trigger(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); +SINT32 sf_data_analysis_sync_cfg(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); + +SF_PARA_TIME_S* sf_server_time_get(void); + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + +#endif + diff --git a/code/application/source/sf_app/code/include/sf_datahttp.h b/code/application/source/sf_app/code/include/sf_datahttp.h new file mode 100755 index 000000000..2bb83e75a --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_datahttp.h @@ -0,0 +1,56 @@ + +#ifndef __SF_TRANSDATA1_H__ +#define __SF_TRANSDATA1_H__ + +#include "sf_type.h" +#include "sf_param_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define SF_DATA_ERROR_REQUEST SF_ERR_ID(SF_MOD_DATA, ERROR_REQUEST) +#define SF_DATA_ERROR_FILE_SEND SF_ERR_ID(SF_MOD_DATA, ERROR_FILE_SEND) +#define SF_DATA_ERROR_IP_CHANGE SF_ERR_ID(SF_MOD_DATA, ERROR_IP_CHANGE) +#define SF_DATA_ERROR_DATA_FORMAT SF_ERR_ID(SF_MOD_DATA, ERROR_DATA_FORMAT) + +typedef struct +{ + char fileName[64]; + int fileType; +}SF_RESERVE_THUMB; +extern LOGIN_ACM_RESPONSE_S stLoginAcmResponse; + +SINT32 sf_net_packetgrouping_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); +SINT32 sf_net_packetgrouping_fileresult(SF_DATA_ATTR_S *pstdata, SF_PDT_PARAM_STATISTICS_S *pStaticParam,SF_REPORT_FILE_ATTR_S *pstfileAttr); + +SINT32 sf_net_packetgrouping_sync(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_net_packetgrouping_disconnection(SF_DATA_ATTR_S *pstdata,SF_VOID *Param); + +SINT32 sf_net_packetanalysis_login(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_net_packetanalysis_fileresult(SF_DATA_ATTR_S *param); + +SINT32 sf_net_packetanalysis_sync(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam); + +LOGIN_ACM_RESPONSE_S* sf_get_login_reponse(void); + +SF_REPORT_FILE_ATTR_S* sf_get_sub_report_file_attr(void); + +SF_REPORT_FILE_ATTR_S* sf_get_thm_report_file_attr(void); + + + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + diff --git a/code/application/source/sf_app/code/include/sf_debug.h b/code/application/source/sf_app/code/include/sf_debug.h new file mode 100755 index 000000000..a7367ceb1 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_debug.h @@ -0,0 +1,68 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: Kola + * Ver: 1.0.0 2021.04.15 + * Description: create +**************************************************************************/ +#ifndef _SF_DEBUG_H_ +#define _SF_DEBUG_H_ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_param_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef SINT32 (*SF_DEBUG_CALLBACK_FN_PTR)(SINT32 argc, SF_CHAR **argv[]); + +typedef struct SF_DEBUG_CMD_ATTR_S { + + SF_CHAR cmdStr[64]; + SF_DEBUG_CALLBACK_FN_PTR pfn_debug_cmd_exe; + +} SF_DEBUG_CMD_ATTR_S; + +SINT32 sf_debug_init(SF_CHAR *filepath,SINT32 *fd); + +SINT32 sf_debug_create(SF_DEBUG_CMD_ATTR_S *pDebugCmdArray,SINT16 lenth); + +SINT32 sf_debug_start(SINT32 fd); + +SINT32 sf_debug_stop(void); + +SINT32 sf_debug_deinit(SINT32 fd); + + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif diff --git a/code/application/source/sf_app/code/include/sf_dev_other.h b/code/application/source/sf_app/code/include/sf_dev_other.h new file mode 100755 index 000000000..c6516f376 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_dev_other.h @@ -0,0 +1,24 @@ +#ifndef __SF_DEV_OTHER_H__ +#define __SF_DEV_OTHER_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_type.h" +#include "sf_hal_gpio.h" + +#include "sf_param_common.h" +SINT32 sf_dev_pir_status_get(void); +UINT16 sf_pir_to_digit_analog(UINT8 pirs); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + diff --git a/code/application/source/sf_app/code/include/sf_dev_usb.h b/code/application/source/sf_app/code/include/sf_dev_usb.h new file mode 100755 index 000000000..b28ea6fe7 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_dev_usb.h @@ -0,0 +1,35 @@ +#ifndef __SF_DEV_USB_H__ +#define __SF_DEV_USB_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_type.h" +#include "sf_hal_gpio.h" + +#include "sf_param_common.h" + +typedef enum sf_USB_MODE_E +{ + SF_USB_APP_CHARGE = 0, + SF_USB_APP_MSDC, + SF_USB_APP_UVC, +}SF_USB_MODE_E; + +void sf_usb_app_mode_set(SF_USB_MODE_E mode); + +SF_USB_MODE_E sf_usb_app_mode_get(void); + +SINT32 sf_usb_IsInsert(void); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + diff --git a/code/application/source/sf_app/code/include/sf_device.h b/code/application/source/sf_app/code/include/sf_device.h new file mode 100755 index 000000000..ed35ec10b --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_device.h @@ -0,0 +1,64 @@ +#ifndef __SF_DEVICE_H__ +#define __SF_DEVICE_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include +#include "sf_param_common.h" +typedef enum sfHAL_LED_GPIO_IDX_E +{ + SF_HAL_LED_IDX_0 = 0, /** +#include +#include +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_param_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#define LOG_TMP_MOD_FILE_PATH SF_SD_ROOT"SF_GPS.TXT" +#define LOG_AT_FILE_PATH SF_SD_ROOT"SF_GPS.TXT" +#define WARNING_FILE_PATH SF_SD_ROOT"warning.txt" +#define INFO_FILE_PATH SF_SD_ROOT"info.txt" + +#define SF_ENCRYPTION_ENBLE 1 + +typedef enum SF_LOG_LEVEL_E +{ + SF_LOG_LEVEL_ERROR = 0, /** + +#define SF_MUTEX_INIT_LOCK(mutex) \ + do { \ + (void)pthread_mutex_init(&mutex, NULL); \ + } while (0) + +#define SF_MUTEX_LOCK(mutex) \ + do { \ + (void)pthread_mutex_lock(&mutex); \ + } while (0) + +#define SF_MUTEX_UNLOCK(mutex) \ + do { \ + (void)pthread_mutex_unlock(&mutex); \ + } while (0) + +#define SF_MUTEX_DESTROY(mutex) \ + do { \ + (void)pthread_mutex_destroy(&mutex); \ + } while (0) + + +#define SF_APPCOMM_CHECK_RETURN(ret, errcode) \ + do { \ + if (SF_SUCCESS != ret) { \ + MLOGE("Error Code: [0x%08X]\n\n", ret); \ + return errcode; \ + } \ + } while (0) +#define SF_APPCOMM_CHECK_OPENFILE_RETURN(ret, str,errcode) \ + do { \ + if (ret < 0) { \ + MLOGE("open file: [%s] failed!!!\n\n", str); \ + return errcode; \ + } \ + } while (0) + +#define SF_CS_CHECK_BERAK(ret) \ + if (SF_SUCCESS != ret) { \ + MLOGE("Error Code: [0x%08X]\n\n", ret); \ + break; \ + } +#define SF_COMM_CHECK_POINTER(p, errcode) \ + do { \ + if (!(p)) { \ + MLOGE("pointer[%s] is NULL\n", #p); \ + return errcode; \ + } \ + } while (0) + +#define SF_TTYUSB_RECV_MAX 580 +#define SF_HTTP_RECV_MAX 4096 + + +#define CFG_FLAT_ANGLE_LEN +//#define CFG_WIDE_ANGLE_LEN + + +#define SF_VER_MAX_LEN 12 + + + +#define SF_BATCH_MAX_NUMBER (2) + +#define SF_CAMERA_NAME_MAX_LEN (12) +#define SF_ICCID_MAX_LEN (22) +#define SF_DAILY_MAX_NUMBER (2) +#define SF_IMEI_MAX_LEN (32) +#define SF_OPERATOR_CODE_MAX_LEN (8) +#define SF_APN_MAX_LEN (40) +#define SF_APN_PASSWORD_MAX_LEN (20) +#define SF_FTP_MAX_LEN (40) +#define SF_FTP_PORT_MAX_LEN (5) +#define SF_GPS_INFO_MAX_LEN (16) +#define SF_MODULE_VER_MAX_LEN (50) +#define SF_BIND_ACCOUNT_MAX_LEN (50) +#define SF_TOKEN_MAX_LEN (64) +#define SF_ALIVE_IP_MAX_LEN (32) +#define SF_UUID_MAX_LEN (32) + + +#define SF_MAX_PATH_LEN 128 +#define SF_MAX_PIC_LEN 64 +#define SF_SRCFILE_MAX 4 +#define SF_THUMB_FILE_MAX_LEN 20 + + +#define GPIOID_PIR_TEST 3 +#define GPIOID_SIM_INSRET 4 +#define GPIOID_USB_INSERT 61 +#define GPIOID_WIFI_POWER 6 +#define GPIOID_USB_MUX1 16 //t100 only one usb mux +#define GPIOID_USB_MUX2 16 + +#define GPIOID_ADC_MUXA 52 +#define GPIOID_ADC_MUXB 53 + +#define GPIOID_IRCUT_MEN1 50 +#define GPIOID_IRCUT_MEN2 51 + + +#define SD_WARNING_SPACE 30 /*30MB*/ + + + +#define HTTP_PORT 80 +#define HTTPS_PORT 443 +#define HTTPCLIENT_REV_SIZE 512 +#define BUFFER_SIZE 2048 + + +#define SF_DEV_NOT_EXIST 20002 +#define SF_DEV_NOT_BIND 20006 +#define SF_SYS_ERR 1 +#define SF_PARA_ERR 3 +#define SF_USER_NOT_EXIST 10006 +#define SF_SIM_NOT_EXIST 30002 +#define SF_SIM_NET_NOT_TURN_ON 30004 +#define SF_SIM_DEV_NOT_BIND 20011 +#define SF_DEV_DETAILS_NOT_VILLAGE 20009 +#define SF_DEV_AUTH_INVALID 401 + + +#define MSYS_IOCTL_MAGIC 'S' +#define IOCTL_MSYS_GET_RTOSSTATUS _IO(MSYS_IOCTL_MAGIC, 0x95) +#define IOCTL_MSYS_GET_MODULE_DATA _IO(MSYS_IOCTL_MAGIC, 0x96) +#define IOCTL_MSYS_GET_SY_RTOS_DATA _IO(MSYS_IOCTL_MAGIC, 0x97) +#define IOCTL_MSYS_SET_RTOS_CMD _IO(MSYS_IOCTL_MAGIC, 0x98) + +#define DEFAULT_RTC_DEVICE "/dev/rtc0" + +#define SF_SD_ROOT "/mnt/sd/" + +#define SIFAR_CUSTOMER_PARAM_PATH "/misc/sfSysParm.bin" +#define SIFAR_STATISTICS_PARAM_PATH "/mnt/sd/DCIM/THUMB/sfStatisticsParm.bin" + + + +#define GPIO_DIR_OUT 1 +#define GPIO_DIR_IN 0 + +#define AMZ_HOST "s3.amazonaws.com" +#define AMZ_PW_TITLE "AWS4" +#define SECRET_TYPE "AWS4-HMAC-SHA256" +#define SECRET_VER "aws4_request" +#define AMZ "s3" + +#define SF_4G_PIC_THUMB_PATH SF_SD_ROOT"DCIM/THUMB/" +#define SF_4G_SMALL_VIDEO_STREAM_PATH SF_SD_ROOT"DCIM/SMALL/" +#define SIM_AUTO_MATCH_FILE_PATH SF_SD_ROOT"SIM Auto Match.TXT" + +#define SF_DCF_DIR_NAME_SUFFIX "SYCAM" /**< DCF Directory Name (it must be 5-characters) */ +#define SF_DCF_ROOT_DIR_NAME "DCIM" /**< DCF Root Directory Name */ +#define SF_DCF_THM_DIR_NAME "THUMB" /**< DCF Directory Name (it must be 5-characters) */ + +#define SF_DCF_EXT_PHOTO "jpg" /**< File extenstion name for Date DB */ +#define SF_DCF_EXT_MOV "mp4" /**< File extenstion name for Date DB */ +#define SF_DCF_EXT_AUDIO "WAV" /**< File extenstion name for Date DB */ +#define SF_DCF_EXT_THM "jpg" /**< File extenstion name for Date DB */ + +#if defined(CFG_FLAT_ANGLE_LEN) +#define SF_DCF_FILE_NAME_PREFIX "HRT1" +#elif defined(CFG_WIDE_ANGLE_LEN) +#define SF_DCF_FILE_NAME_PREFIX "SWT1" +#else +#define SF_DCF_FILE_NAME_PREFIX "SYEW" +#endif + + + + +#define SF_QLOG_ENABLE 1 +//#define SF_VERSION_RELEASE +//#define SF_HARDWARE_TEST +//#define SF_FACTORY_TEST +//#define SF_GPS_TEST +#define SF_EMC_TEST + +#define CMD_SHORT_LONG_CLICK_OFFSET (128) + +#ifdef SF_VERSION_RELEASE +#define ACCESS_KEY "ACT1CSHKRO01" +#else +#define ACCESS_KEY "AC40CSHKRO01" +#endif + +#define SF_ERR_ID(module, err) ((SINT16)(((module) << 8) | (err))) +/** SF Module ID */ +typedef enum SF_MOD_e { + + SF_MOD_4G = 1, + SF_MOD_GPS, + SF_MOD_FILE, + SF_MOD_HTTP, + SF_MOD_TTY, + SF_MOD_DATA, + SF_MOD_COM, + SF_MOD_LOG, + SF_MOD_STORE, + SF_MOD_SYS, + SF_MOD_APP, + SF_MOD_BUTT, +} SF_MOD_E; + +typedef enum ERR_CODE_e{ + ERROR_AT_APN, + ERROR_AT_TIMEOUT, + ERROR_AT_ACTIVE, + ERROR_AT_READ, + ERROR_AT_WRITE, + ERROR_AT_OPEN, + ERROR_AT_DISCONNECT, + ERROR_NO_SIMCARD, + ERROR_NO_SUPPORT, + ERROR_NO_SIGNAL, + ERROR_NO_FILE, + ERROR_FILE_SEND, + ERROR_INS_EXIT, + ERROR_NOT_MATCH, + ERROR_IP_ADDR, + ERROR_IP_CHANGE, + ERROR_REQUEST, + ERROR_WRITE, + ERROR_DATA_FORMAT, + ERROR_MODULE_OPEN, + ERROR_REG_NET, + ERROR_BUTT, +}ERR_CODE_E; +typedef enum sf_FILE_TYPE_E + +{ + SF_FILE_TYPE_PIC_THUM_3M = 0x00, + SF_FILE_TYPE_PIC_3M = 0x01, + SF_FILE_TYPE_VIDEO_THUM_WVGA = 0X02, + SF_FILE_TYPE_VIDEO_WVGA = 0X03, + SF_FILE_TYPE_VIDEO_THUM_720P = 0X04, + SF_FILE_TYPE_VIDEO_720P = 0X05, + SF_FILE_TYPE_VIDEO_THUM_1080P = 0X06, + SF_FILE_TYPE_VIDEO_1080P = 0X07, + SF_FILE_TYPE_PIC_THUM_5M = 0x08, + SF_FILE_TYPE_PIC_5M = 0x09, + SF_FILE_TYPE_LOG_ERROR = 0x0A, + SF_FILE_TYPE_CFG = 0x0B, + SF_FILE_TYPE_TRIGGER = 0x0C, + + SF_FILE_TYPE_PIC_BIG, + SF_FILE_TYPE_PIC_SMALL, + SF_FILE_TYPE_PIC_VIDEO, + SF_FILE_TYPE_VIDEO, + SF_FILE_TYPE_LOG_DP, /*dailyreport file*/ + SF_FILE_TYPE_GPS, + SF_FILE_TYPE_TXT, + SF_FILE_TYPE_UPDATE, + SF_FILE_TYPE_FOTA, + SF_FILE_TYPE_BT_ALARM, /*Bettery Alarm*/ + SF_FILE_TYPE_OTHER, + SF_FILE_TYPE_BUTT, +}SF_FILE_TYPE_E; + +typedef enum { + SF_USB_MUX_HOST_4G = 0, + SF_USB_MUX_PC_4G = 1, + SF_USB_MUX_PC_HOST =2, + SF_USB_MUX_MAX = 3, +}SF_USB_MUX_FUN_e; + +typedef enum sfSD_STATUS_E +{ + SF_SD_UNPLUGED = 0x00, + SF_SD_OUT, + SF_SD_OK, + SF_SD_FULL, + SF_SD_ERROR, + SF_SD_PLUGED, + SF_SD_BUTT, +} SF_SD_STATUS_E; + +typedef enum sf_STARTUP_TYPE_E +{ + SF_MCU_STARTUP_OFF = 0x00,/* POWER OFF*/ + SF_MCU_STARTUP_ONKEY = 0x01,/*key on SETUP*/ + SF_MCU_STARTUP_TIMELAPSE = 0x02,/*timelapse power on*/ + SF_MCU_STARTUP_NORMAL = 0x03,/*Dial the key to ON*/ + SF_MCU_STARTUP_RING = 0x04,/*ring power on*/ + SF_MCU_STARTUP_PIR = 0x05,/*pir power on*/ + SF_MCU_STARTUP_WARNING = 0x06,/*low bat worning power on*/ + SF_MCU_STARTUP_SERVER = 0x07,/*server power on(reserve)*/ + SF_MCU_STARTUP_DP = 0x08,/*DailyReport power on*/ + SF_MCU_STARTUP_USB = 0x09,/*USB power on*/ + SF_MCU_STARTUP_RESET = 0x0A,/*power on to reset(reserve)*/ + SF_MCU_STARTUP_SYN_PARAM = 0x0B,/*power on to syn param(reserve)*/ + SF_MCU_STARTUP_BATCH_SEND= 0x0C,/*power on to send batch*/ + SF_MCU_STARTUP_BUTT = 0X0D, +} SF_STARTUP_TYPE_E; + +typedef enum sfPOWEROFF_TYPE_E +{ + SF_POWEROFF_NOT = 0x00, + SF_POWEROFF_AUTO = 0x01, /*auto power when 3min no operation*/ + SF_POWEROFF_REBOOT = 0x02, /*poweroff to reboot*/ + SF_POWEROFF_KEYON = 0x03, + SF_POWEROFF_KEYOFF = 0x04, + SF_POWEROFF_SYNC_PARAM = 0x05, + SF_POWEROFF_GPS_DP = 0x06, + SF_POWEROFF_SD_FULL = 0x07, + SF_POWEROFF_LOW_BAT = 0x08, + SF_POWEROFF_NO_SD = 0x09, + SF_POWEROFF_BUTT, +} SF_POWEROFF_TYPE_E; + +typedef enum sf_CAMMODE_E +{ + SF_CAMMODE_PIC = 0, + SF_CAMMODE_VIDEO , + SF_CAMMODE_PV, /* pic+video*/ + SF_CAMMODE_BUTT +}SF_CAMMODE_E; +typedef enum sf_IMG_SIZE_E +{ + SF_IMG_SIZE_32M = 0, + SF_IMG_SIZE_24M, + SF_IMG_SIZE_12M, + SF_IMG_SIZE_8M, + SF_IMG_SIZE_5M, + SF_IMG_SIZE_3M, + SF_IMG_SIZE_BUTT +}SF_IMG_SIZE_E; +typedef enum sf_VIDEO_SIZE_E +{ + SF_VIDEO_SIZE_1080 = 0, + SF_VIDEO_SIZE_720, + SF_VIDEO_SIZE_WVGA, + SF_VIDEO_SIZE_BUTT +}SF_VIDEO_SIZE_E; +typedef enum sfBAT_TYPE_E +{ + SF_BAT_AL = 0x00, + SF_BAT_NI = 0x01, + SF_BAT_LI = 0x02, + SF_BAT_CUS_LI = 0x03, + SF_BAT_BUTT, +} BAT_TYPE_E; +typedef enum sf_MESSAGE_TYPE_E +{ + CMD_KEY = 0x1A00, + CMD_SD = 0x1B00, + CMD_LED = 0x1C00, + CMD_FILE = 0x1D00, + CMD_POWEROFF = 0x1E00, + CMD_VENC = 0x1F00, + +}SF_MESSAGE_TYPE_E; + + +typedef enum sf_MESSAGE_CMD_SD_e +{ + CMD_SD_MOUNT_SUCCESS = 0x01, + CMD_SD_ERROR = 0x02, + CMD_SD_OUT = 0x03, + CMD_SD_FULL = 0x04, + CMD_SD_MOUNT_FAILURE = 0x05, + +}SF_MESSAGE_CMD_SD_E; + +typedef enum sf_MESSAGE_CMD_LEDD_e +{ + + CMD_LED_EVT = 0x01, + +}SF_MESSAGE_CMD_LED_E; + +typedef enum sf_MESSAGE_CMD_VENC_e +{ + + CMD_VENC_START_SUCCESS = 0x01, + CMD_VENC_START_FAILURE = 0x02, + CMD_VENC_STOP_SUCCESS = 0x03, + CMD_VENC_STOP_FAILURE = 0x04, + CMD_VENC_STREAM_START = 0x05, + CMD_VENC_STREAM_STOP = 0x06, +}SF_MESSAGE_CMD_VENC_E; +#ifdef CFG_TRANSDATA_AT + +typedef enum sf_UPLOAD_STATUS_E{ + SF_UPLOAD_FTP = 0x01, + SF_UPLOAD_OSS, + SF_UPLOAD_AMZ, + SF_UPLOAD_BUTT, +} SF_UPLOAD_STATUS_E; +#else +typedef enum sf_UPLOAD_STATUS_E{ + SF_UPLOAD_FTP = 0x00, + SF_UPLOAD_OSS, + SF_UPLOAD_AMZ, + SF_UPLOAD_BUTT, +} SF_UPLOAD_STATUS_E; +#endif + + +typedef enum sf_DATE_TYPE_E{ + DATE_TYPE_YYMMDD = 0, + DATE_TYPE_MMDDYY, + DATE_TYPE_DDMMYY, + DATE_TYPE_BUTT, +} SF_DATE_TYPE_E; +typedef enum sf_SIM_TYPE_E +{ + SF_SIM_MEGA = 0, // normal mega sim, use in abroad + SF_SIM_MEGA_IOT, //special mega sim, only use in T110 + SF_SIM_OTHER, //other sim + SF_SIM_BUTT +}SF_SIM_TYPE_E; + + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + diff --git a/code/application/source/sf_app/code/include/sf_param_struct.h b/code/application/source/sf_app/code/include/sf_param_struct.h new file mode 100755 index 000000000..060fc84bd --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_param_struct.h @@ -0,0 +1,359 @@ +#ifndef __SF_PARAM_STRUCT_H__ +#define __SF_PARAM_STRUCT_H__ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include + +#include "sf_type.h" +#include "sf_param_enum.h" + + +typedef struct sf_URL_s { + SF_CHAR url[160]; +}SF_URL_S; + +typedef struct sf_OSS_s { + UINT8 szIP[64]; + UINT8 szBucket[32]; + UINT8 szUsername[32]; + UINT8 szPassword[48]; +}SF_OSS_S; + +typedef struct sf_THREAD_CFG_S { + unsigned char IsRun; + unsigned char IsStopFlag; + pthread_t TskId; +} SF_THREAD_CFG_S ; + +#ifndef SF_DATA_UI_TYPE +#define SF_DATA_UI_TYPE +#define SF_TIMER_MAX_NUMBER (2) +typedef struct SF_PARA_TIME_S { + + UINT16 Year; + UINT16 Mon; + UINT16 Day; + + UINT16 Hour; + UINT16 Min; + UINT16 Sec; +} SF_PARA_TIME_S; + +typedef struct SF_WORKTIME_S +{ + SF_PARA_TIME_S StartTime; + SF_PARA_TIME_S StopTime; +} SF_WORKTIME_S; + +#endif + +typedef struct sf_subscribe_ATTR_S { + UINT8 subscribeType; + char subscribeFileName[40]; +}SF_SUBSCRIBE_ATTR_S; + +typedef struct sf_subscribe_file_ATTR_S { + UINT8 subscribeCnt; + SF_SUBSCRIBE_ATTR_S *pSubscribe; +}SF_SUBSCRIBE_FILE_ATTR_S; + +#ifndef SF_PDT_PARAM_CFG_S +typedef struct sfPDT_PARAM_CFG_S +{ + /*camera param*/ + UINT8 WorkMode; + UINT8 CamMode; // Picture, Video, Picture+Video + UINT8 ImgSize; // 8M, 16M, 32M + UINT8 VideoSize; // WVGA, 720P, 1080P + UINT8 VideoLenth; + UINT8 Multishot; // shot picture number 1~5,1 single shot 2~5 continuous shot + UINT8 MultishotInterval; // shot interval. 0: shot in one second; 1: 1 pic per sec; 2: 2 pic per sec + UINT8 NightMode; + UINT8 FlashLed; + UINT8 PirSensitivity; + UINT8 PirDelaySwitch; /*DelayFlag;*/ + UINT8 TimelapseSwitch; + UINT8 WorkTime1Switch; /*WorkTime*/ + UINT8 WorkTime2Switch; /*WorkTime*/ + UINT8 CameraNameFlag; + UINT8 PirSwitch; + UINT8 SdLoop; /*SdCycle*/ + UINT8 DigitPirSensitivity; + + UINT8 DailyReportswitch; + UINT8 ReDailyReport; /*if network error, reboot an hour later,liteOS need this param,not separete*/ + UINT8 FristSendDailyAndGps; + + UINT8 GprsMode; /*0:Daily, 1:Intant*/ + UINT8 GprsSwitch; /*0:gprs off, 1:gprs on*/ + UINT8 SendMaxNum; + UINT8 SendPicSize; // thumbnail 0:640*480, 1:1920*1440 + UINT8 SendType; /*0:send immediately, 1:send once per day, 2:send twice per day*/ + UINT8 SendMultishot; + UINT8 SendVideo; + UINT8 SendPhoto; + + UINT8 BatteryType; + UINT8 StampSwitch; + UINT8 DateStyle; + UINT8 DebugMode; + UINT8 Zoom; // APP preview magnification, 1x,2x,4z + UINT8 LightFreq; // 50HZ, 60H + SINT8 TimeZone; + + UINT8 GpsSwitch; /*0:OFF 1:ON*/ + UINT8 GpsSendType; /*0:when camera trun on 1: one time 2:twice time*/ + UINT8 DateAuto; + UINT8 PicUponDailyReport; + UINT8 FtpSwitch; + UINT8 VideoFrame; + UINT8 ParaSync; + UINT16 RTCYear; + UINT8 RtcMonth; + UINT8 RTCDay; + UINT8 RTCHour; + UINT8 RTCMinute; + UINT8 RTCSecond; + UINT8 FirstUpdateFlag; /*1: indicate first update start*/ + UINT8 FormateFlag; + UINT8 Formatestatus; + UINT8 ResetFlag; + UINT8 GPSFlag; + UINT8 BatchSendTimelapse; + UINT8 GPSEnterResetModeFlag; + UINT8 GPSWaitRestartFlag; + UINT8 GPSMapeUpdateFlag; + UINT8 GPSAntitheftFlag; + UINT8 Lastsetuptype; + UINT8 OtaFlag; + SF_PARA_TIME_S TimelapseTime; + SF_WORKTIME_S WorkTime[SF_TIMER_MAX_NUMBER]; + SF_PARA_TIME_S PirDelayTime; + SF_PARA_TIME_S DailyReportTime; + SF_PARA_TIME_S TimeSend1;/*batch send1 time*/ + + char CameraNameStr[SF_CAMERA_NAME_MAX_LEN]; + UINT32 CheckSum; +}SF_PDT_PARAM_CFG_S; +#endif +typedef struct sfPDT_PARAM_STATISTICS_S +{ + /*DailyReport Part*/ + UINT8 DailyReportNum;/*0:OFF, 1:one time per day, 2:two Times per day*/ + UINT16 DialyReportFailCnt; + UINT16 Year; + UINT16 Mon; + UINT16 Day; + + UINT16 TriggerTimes; + UINT8 SubscribeSendCnt; + UINT8 SubVideoSendCnt; + UINT8 SendBatchAgain; /*copy from 3.8CG needReConcentratedSend*/ + UINT8 DailyReportAgain; /* copy from 3.8CG ReDailyFlag:if network error, reboot an hour later*/ + UINT16 SendPicDayCnt; /*copy from 3.8CG picSendMax, send success pic number per day*/ + UINT16 SendDailyCnt; /*send pic count success+fail*/ + UINT16 SendDailyThumbCnt;/* send small pic times, success + fail*/ + UINT16 SendSuccessThumbCnt;/* send small pic times, success*/ + UINT16 SendDailyOriginalCnt; + UINT16 SendSuccessOriginalCnt; + UINT16 SendDailyVideoCnt;/* send video times, success + fail*/ + UINT16 SendSuccessVideoCnt;/* send video times,success*/ + UINT32 SendThumbTotalTime;/* send small pic time, uint:second*/ + UINT32 SendOriginalTotalTime; + UINT32 SendVideoTotalTime;/* send video time, uint:second*/ + + UINT32 OldFileKey; + UINT16 SdTotalFile; + UINT16 SendDailyFailCnt; + UINT16 SendDailyTimeoutCnt; + UINT16 SynParamFlag; + UINT16 SynMcuSet; /* 1: set sync 0: not set (void)*/ + UINT8 InstantFtpRecfg; /*1: must cfg ftps , 0 : do not cfg ftps*/ + UINT8 GpsPowerONSendFlag; /*1: send gps txt when first time to on 0: send gps txt base gps num setting*/ + UINT8 LoginACMFailedCnt; + UINT8 u8GetPicFlag; + UINT8 u8ResetLimited; + UINT8 bindFlag; + UINT8 GPSInfoGetFailed; + UINT8 SimType; + + /*SIM Card Info*/ + char OperatorCode[SF_OPERATOR_CODE_MAX_LEN]; + //char Carrier[64]; + char ApnGPRS[SF_APN_MAX_LEN]; + char ApnUsername[SF_APN_MAX_LEN]; + char ApnPassword[SF_APN_PASSWORD_MAX_LEN]; + char ServiceProvider[64]; + + char MMSC[SF_APN_MAX_LEN]; + char MMSAPN[SF_APN_MAX_LEN]; + char Proxy[SF_APN_MAX_LEN]; + char Port[SF_APN_MAX_LEN]; + char UserName[SF_APN_MAX_LEN]; + char Password[SF_APN_MAX_LEN]; + /*ftp info*/ + char WebIP[SF_FTP_MAX_LEN]; + char AcmIP[64]; + + + /*SIM Card Info*/ + char IMEI[SF_IMEI_MAX_LEN]; + char SimID[SF_ICCID_MAX_LEN]; + char ModuleVersion[SF_MODULE_VER_MAX_LEN]; + char ModuleSubversion[SF_MODULE_VER_MAX_LEN]; + /*GPS INFO*/ + UINT16 GpsSendFlag; + UINT16 GpsSendYear; + UINT16 GspSendMon; + UINT16 GpsSendDay; + SINT32 Did; + SINT32 AlivePort; + UINT8 UploadMode; + char GpsInfo[SF_GPS_INFO_MAX_LEN]; + char Latitude[SF_GPS_INFO_MAX_LEN]; + char Longitude[SF_GPS_INFO_MAX_LEN]; + char BindAccount[SF_BIND_ACCOUNT_MAX_LEN]; + + char Token[SF_TOKEN_MAX_LEN]; + char AliveIp[SF_ALIVE_IP_MAX_LEN]; + char Uuid[SF_UUID_MAX_LEN]; + /*Low Power Alarm */ + UINT16 LowPowerAlarmFlag; /*0: no alarm upload, 1: alarm already upload.*/ + char PicPlan; + UINT8 startup; + UINT8 FcTemper; + UINT8 BatRemainCap; + UINT8 OtaUpgradeFlag; + + UINT8 netGeneration; + UINT8 SimSignal; + SF_SUBSCRIBE_FILE_ATTR_S stSubscribe; + SF_OSS_S stOssCfg; + SF_PARA_TIME_S httpTime; + + UINT32 CheckSum; +}SF_PDT_PARAM_STATISTICS_S; + +typedef struct sf_FILE_ATTR_S { + + SF_FILE_TYPE_E enFileTye; + SF_CHAR thumbfileName[SF_MAX_PIC_LEN]; + SF_CHAR thumbfilePath[SF_MAX_PATH_LEN]; + SF_CHAR txtfilePath[SF_MAX_PATH_LEN]; + SF_CHAR txtfileName[SF_MAX_PIC_LEN]; + UINT32 thumbfileSize; + +}SF_FILE_ATTR_S; + +typedef struct sf_SEND_FILE_ATTR_S { + + SF_FILE_TYPE_E enFileTye; //upload sub hd or video file type; upload batch send thumb file type; + SF_CHAR SubFileName[SF_MAX_PIC_LEN]; //sub hd or video file name, use as bind file; when batch send thumb file, this is null. + SF_CHAR SendFileName[SF_MAX_PIC_LEN];//upload sub hd or video file name; upload batch send thumb file name; + UINT32 SendFileSize; //upload sub hd or video file size; upload batch send thumb file size; + UINT32 SendRet; //0:send success; other:error code + UINT8 SameFlag; + +}SF_SEND_FILE_ATTR_S; + +typedef struct sf_SRCFILE_ATTR_S { + UINT8 filecnt; + SF_FILE_ATTR_S stfileattr[SF_SRCFILE_MAX]; +}SF_SRCFILE_ATTR_S; +typedef struct sf_REPORT_FILE_ATTR_S { + UINT8 filecnt; + SF_SEND_FILE_ATTR_S stSendFileAttr[100]; +}SF_REPORT_FILE_ATTR_S; + +typedef struct sf_MESSAGE_Buf_S +{ + long mtype; + SINT32 cmdId; + SINT32 s32Wait; + SINT32 arg1; + SINT32 arg2; + SINT32 arg3; +}SF_MESSAGE_BUF_S; +typedef struct sf_RtosInfo_t{ + unsigned int test1; + unsigned int test2; + unsigned int test3; + unsigned int IsNight; + unsigned int BatPer; + unsigned int Fctemp; + unsigned short McuVer; + unsigned char McuSubVer; + unsigned int rtosBootTime; +} SF_RTOSINFO_S; +typedef struct SF_RTOS_CMD_s{ + unsigned char cmd; + unsigned char arg[8]; + unsigned char info[256]; +} SF_RTOS_CMD_T; + +typedef struct sf_THREAD_S +{ + SF_BOOL IsRun; /** max)\ + {\ + MLOGE("Parameter[%d] out of normal range [%d,%d)!!!\n",cmd,min,max);\ + return SF_FAILURE;\ + } \ + } while (0) + + +typedef enum { + SF_SD_FORMAT_SUCUSS = 0, + SF_SD_FORMAT_NO_CARD = 1, + SF_SD_FORMAT_NOT_SUPPORT_FAT =2, + SF_SD_FORMAT_MAX = 3, +}SF_SD_FORMAT_RESULT_e; +typedef struct sf_STORE_ATTR_S { + + U32 SDStatus; + U32 SDFree; + U32 SDTotalSize; + +}SF_STORE_ATTR_S; + + + +SINT32 sf_sd_info_get(SF_STORE_ATTR_S *pstoreattrs); + +SINT32 sf_sd_remove_file(const char *path,SINT32 threshold) ; + +SINT32 sf_sd_loopremove(const char *path); + +SINT32 sf_sd_isfull(SINT8 *Isfull); + +SF_SD_STATUS_E sf_sd_status_get(void); + +SINT32 sf_sd_status_set(SF_SD_STATUS_E enStatus); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /*_SF_COMMON_H_*/ + diff --git a/code/application/source/sf_app/code/include/sf_systemMng.h b/code/application/source/sf_app/code/include/sf_systemMng.h new file mode 100755 index 000000000..06d91321c --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_systemMng.h @@ -0,0 +1,83 @@ +#ifndef _SF_SYSTEMMNG_H_ +#define _SF_SYSTEMMNG_H_ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_param_common.h" +#define SF_SYS_CHECK_RANGE(cmd, min,max) \ + do { \ + if(cmd < min || cmd > max)\ + {\ + MLOGE("Parameter[%d] out of normal range [%d,%d)!!!\n",cmd,min,max);\ + return SF_FAILURE;\ + } \ + } while (0) + +// following define must be same to "kernel\drivers\sstar\include\mdrv_msys_io.h" + +#define SF_VER_FILE_PATH SF_SD_ROOT"CAM_INFO.txt" + +typedef enum sfUPGRADE_STATUS_E +{ + SF_UPGRADE_PRE = 0x01, /*Upgrade*/ + SF_UPGRADE_ING, /*upgrade ing*/ + SF_UPGRADE_FAIL, /*upgrade fail*/ + SF_UPGRADE_SUCCESS, + SF_UPGRADE_BUTT, +} SF_UPGRADE_STATUS_E; + +typedef enum +{ + LINUX2RTK_CMD_STOP_RECORD = 1, // stop record venc chn + LINUX2RTK_CMD_SET_RTKMODE = 2, // set work mode to rtk,for manual control mode + LINUX2RTK_CMD_SET_POWEROFF = 3, // set POWEROFF type + LINUX2RTK_CMD_SET_RTCTIME = 4, // set rtc time + LINUX2RTK_CMD_SET_DEVINFO = 5, // set dev info + LINUX2RTK_CMD_SET_UVCCTRL = 6, // set rtos uvc ctrl,open/close + LINUX2RTK_CMD_SET_P2PCTRL = 7, // set rtos p2p live ctrl,open/close + LINUX2RTK_CMD_SET_OTHER = 8, + LINUX2RTK_CMD_SET_BUTT +} CUS_LINUX2RTK_CMD_E; +SF_UPGRADE_STATUS_E sf_upgrade_status_get(void); + +void sf_upgrade_status_set(SF_UPGRADE_STATUS_E status); + +SF_POWEROFF_TYPE_E sf_poweroff_type_get(void); + +SINT32 sf_poweroff_type_set(SF_POWEROFF_TYPE_E enType); + +SINT32 sf_sys_rtc_time_get(SF_PARA_TIME_S *pstDateTime); + +SINT32 sf_sys_rtc_time_set(SF_PARA_TIME_S* pstDateTime); + +SINT32 sf_sys_rtc_time_check(SF_PARA_TIME_S *pstDateTime); + +SINT32 sf_sys_rtc_time_reset(void); + +SINT64 sf_sys_os_time_get(void); + +SINT64 sf_sys_os_utime_get(void); + +SINT32 sf_sys_software_version_get(SF_CHAR* version); + +SINT32 sf_sys_camera_about(void); + +SINT32 sf_sys_rtoscmd_set(SINT8 cmd, SINT8 *para); + +SINT32 sf_sys_rtosdata_get(SF_RTOSINFO_S *pstRtosData); + +SINT32 sf_sys_poweroff(SF_POWEROFF_TYPE_E poweroffType); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + +#endif + + diff --git a/code/application/source/sf_app/code/include/sf_transdata1.h b/code/application/source/sf_app/code/include/sf_transdata1.h new file mode 100755 index 000000000..145a1f06a --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_transdata1.h @@ -0,0 +1,53 @@ + +#ifndef __SF_TRANSDATA1_H__ +#define __SF_TRANSDATA1_H__ + +#include "sf_type.h" +#include "sf_param_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#define SF_DATA_ERROR_REQUEST SF_ERR_ID(SF_MOD_DATA, ERROR_REQUEST) +#define SF_DATA_ERROR_FILE_SEND SF_ERR_ID(SF_MOD_DATA, ERROR_FILE_SEND) + +SINT32 sf_packetgrouping_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_packetgrouping_fileresult(SF_DATA_ATTR_S *pstdata, SF_PDT_PARAM_CFG_S *pstParam,SF_FILE_ATTR_S *pstfileAttr); + +SINT32 sf_packetgrouping_get_bind_account(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_packetgrouping_query_cmd(SF_DATA_ATTR_S *pstdata); + +SINT32 sf_packetgrouping_query_cmd_param(SF_DATA_ATTR_S *pstdata); + +SINT32 sf_packetgrouping_cmd_report(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam, SF_FILE_ATTR_S *pstfileAttr); + +SINT32 sf_packetgrouping_disconnection(SF_DATA_ATTR_S *pstdata,SF_VOID *Param); + +SINT32 sf_MultiPacket_Parsing(UINT16 enCmdID,UINT16 *pdatahead,SF_DATA_ATTR_S *pdatattr); + +SINT32 sf_packetanalysis_login(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_packetanalysis_fileresult(SF_DATA_ATTR_S *param); + +SINT32 sf_packetanalysis_query_cmd(SF_DATA_ATTR_S *param); + +SINT32 sf_packetanalysis_query_cmd_param(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_packetanalysis_trigger(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam); + +SINT32 sf_packetanalysis_bind_account(SF_DATA_ATTR_S *param,SF_FN_PARAM_S *pfnParam); + +SINT32 sf_packetanalysis_cmd_report(SF_DATA_ATTR_S *param); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + diff --git a/code/application/source/sf_app/code/include/sf_type.h b/code/application/source/sf_app/code/include/sf_type.h new file mode 100755 index 000000000..53fd5ff95 --- /dev/null +++ b/code/application/source/sf_app/code/include/sf_type.h @@ -0,0 +1,54 @@ +#ifndef _SF_TYPE_H_ +#define _SF_TYPE_H_ + +#include "kwrap/nvt_type.h" +#ifndef SF_DATA_TYPE +#define SF_DATA_TYPE + + +//typedef unsigned long int UINT64; +//typedef unsigned int UINT32; //hd_type.h:157 +typedef unsigned short UINT16; +typedef unsigned char UINT8; + +typedef signed long int SINT64; +typedef signed int SINT32; +typedef signed short SINT16; +typedef signed char SINT8; + +typedef unsigned char UCHAR; +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned int U32; +typedef unsigned int long ULONG; +typedef unsigned long int U64; + +//typedef signed char CHAR;//hd_type.h:169 +typedef char S8; +typedef short S16; +typedef int S32; +typedef long SLONG; +typedef signed long int S64; + + + + + +typedef char SF_CHAR; + +typedef unsigned char SF_BOOL; + +typedef void SF_VOID; + + +#define SF_NULL 0L +#define SF_SUCCESS 0 +#define SF_FAILURE (-1) + +#define SUCCESS 0 +#define FAIL 1 + +#define SF_TRUE 1 +#define SF_FALSE 0 +#endif +#endif \ No newline at end of file diff --git a/code/application/source/sf_app/code/include/sha256.h b/code/application/source/sf_app/code/include/sha256.h new file mode 100755 index 000000000..5af8c29e5 --- /dev/null +++ b/code/application/source/sf_app/code/include/sha256.h @@ -0,0 +1,33 @@ +#include "sf_type.h" + +#define SHA256_HASH_SIZE 32 + +/* Hash size in 32-bit words */ +#define SHA256_HASH_WORDS 8 + +struct _SHA256Context { + unsigned long long totalLength; + UINT32 hash[SHA256_HASH_WORDS]; + UINT32 bufferLength; + union { + UINT32 words[16]; + UINT8 bytes[64]; + } buffer; +#ifdef RUNTIME_ENDIAN + int littleEndian; +#endif /* RUNTIME_ENDIAN */ +}; + +typedef struct _SHA256Context SHA256Context; + +#ifdef __cplusplus +extern "C" { +#endif + + void SHA256Init (SHA256Context *sc); + void SHA256Update (SHA256Context *sc, const void *data, UINT32 len); + void SHA256Final (SHA256Context *sc, UINT8 hash[SHA256_HASH_SIZE]); + +#ifdef __cplusplus +} +#endif diff --git a/code/application/source/sf_app/code/include/split.h b/code/application/source/sf_app/code/include/split.h new file mode 100755 index 000000000..0881dc402 --- /dev/null +++ b/code/application/source/sf_app/code/include/split.h @@ -0,0 +1,57 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SPLIT_H__ +#define __SPLIT_H__ + +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * Split the input string (null terminated) into QRinput. + * @param string input string + * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8. + * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS. + * @retval 0 success. + * @retval -1 an error occurred. errno is set to indicate the error. See + * Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* __SPLIT_H__ */ diff --git a/code/application/source/sf_app/code/source/4gMng/sf_eg91_gps.c b/code/application/source/sf_app/code/source/4gMng/sf_eg91_gps.c new file mode 100755 index 000000000..de505fbc2 --- /dev/null +++ b/code/application/source/sf_app/code/source/4gMng/sf_eg91_gps.c @@ -0,0 +1,1027 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "sf_type.h" +#include "sf_log.h" +#include "sf_hal_ttyusb.h" +#include "sf_eg91_server.h" +#include "sf_eg91_gps.h" +#include "sf_param_common.h" +#include "sf_module.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +static unsigned long int gps_get_seconds(SF_PARA_TIME_S *pTime) +{ + unsigned long int res = 0; + SF_PARA_TIME_S sfparamtime = {0}; + + memcpy(&sfparamtime,pTime,sizeof(SF_PARA_TIME_S)); + if(sfparamtime.Mon <= 2) + { + sfparamtime.Mon += 10; + sfparamtime.Year -= 1; + } + else + { + sfparamtime.Mon -= 2; + } + + res = (UINT32)(sfparamtime.Year/4 -sfparamtime.Year/100 +sfparamtime.Year/400) + 367*sfparamtime.Mon/12 + sfparamtime.Day + sfparamtime.Year * 365 -719499; + res = ((res*24 + sfparamtime.Hour) * 60 + sfparamtime.Min)*60 + sfparamtime.Sec; + + return res; + +} +static int gps_diffSec_from_date(SF_PARA_TIME_S *pnowDate, SF_PARA_TIME_S *poldDate) +{ + int diffSec = gps_get_seconds(pnowDate) - gps_get_seconds(poldDate); + return diffSec; +} + +static void gps_infor_convert(SF_CHAR *str) +{ + SF_CHAR strTemp[32] = { 0 }; + UINT32 temp; + + memcpy((char*)strTemp, str, 4); + temp = atoi(strTemp); + temp = temp * 60 / 100; + sprintf(strTemp, "%04d", temp); + memcpy(str, strTemp, 4); +} + +SINT16 eg91_gps_greendate_Get(SF_FN_PARAM_S *pfnParam,SF_PARA_TIME_S *pNowTime) + { + SINT16 ttyRet = SF_SUCCESS; + SINT16 ret = SF_SUCCESS; + SINT16 sts = 1; + UINT16 timeout_count = 0; + UINT16 callTime = 0; + UINT8 reHttpSRequest=0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR dataStr[SF_TTYUSB_RECV_MAX] = { 0 }; + MODULE_SERVER_AUTHEN_E enATcmdType = MODULE_HTTP_AUTHEN_AT_QIACT_PRE; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch(enATcmdType) + { + case MODULE_HTTP_AUTHEN_AT_QIACT_PRE: + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QIACT; + break; + case MODULE_HTTP_AUTHEN_AT_QIACT: + sprintf(ttyData,"AT+QIACT=%d\r",HTTP_PDP);/**/ + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPURL_1: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + sprintf(dataStr,"http://acenter.wuyuantech.com/CameraManager/device/getGreenDate"/*, pStaticParam->WebIP*/); + sprintf(ttyData, "AT+QHTTPURL=%d,80\r",strlen(dataStr)); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_2; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(strstr(ttyData, "ERROR")) + { + callTime++; + if(callTime < PDP_TRY_TIME) + { + sf_sleep_s(2); + sprintf(ttyData, "AT+QIACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + callTime=0; + sts = 0; + ret = SF_GPS_ERROR_QIACT; + SLOGE("Moudle QIACT ERROR.DATA:%s", ttyData); + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + + + } + } + else if(timeout_count > 100) + { + sts = 0; + ret = SF_GPS_ERROR_QIACT; + SLOGE("Moudle QIACT timeout"); + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPURL_2: + if(strstr(ttyData, "CONNECT")) + { + timeout_count = 0; + sprintf(ttyData,"http://acenter.wuyuantech.com/CameraManager/device/getGreenDate"/*, pStaticParam->WebIP*/); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPGET; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPGET: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + sprintf(ttyData,"%s","AT+QHTTPGET=80\r"); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPREAD; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPREAD: + timeout_count = 0; + callTime++; + if(strstr(ttyData, "+QHTTPGET:")) + { + if(strstr(ttyData, "+QHTTPGET: 0,200")) + { + timeout_count= 0; + callTime = 0; + sprintf(ttyData,"%s","AT+QHTTPREAD=80\r"); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QIDEACT; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(reHttpSRequest == 0) + { + SLOGW("HTTP Send Failed,try again"); + reHttpSRequest = 1; + sprintf(ttyData,"%s","AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + } + else + { + SLOGE("HTTP Send Failed,data:%s", ttyData); + SLOGE("FAILED:send http failed!!!!!\n"); + + ret = SF_HTTP_ERROR_REQUEST; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + else + { + if((strstr(ttyData,"ERROR")) || (callTime > 400)) + { + if(reHttpSRequest == 0) + { + SLOGD("FAILED:send http timeout,try again\n"); + reHttpSRequest = 1; + sprintf(ttyData,"%s","AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + } + else + { + SLOGD("FAILED:send http timeout!!!!!\n"); + ret = SF_HTTP_ERROR_REQUEST; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + } + } + + } + break; + + case MODULE_HTTP_AUTHEN_AT_QIDEACT: + timeout_count = 0; + if(strstr(ttyData,"statu")) + { + UINT8 *P1 = NULL; + + P1 = strstr(ttyData,"greenDate"); + if(P1 != NULL) + { + //printf("greenDate:%s\n",P1); + UINT8 tempStr[5] = {0}; + + strncpy(tempStr,P1+12,4); + pNowTime->Year = atoi(tempStr); + + memset(tempStr,'\0',sizeof(tempStr)); + strncpy(tempStr,P1+12+4,2); + pNowTime->Mon = atoi(tempStr); + + strncpy(tempStr,P1+12+6,2); + pNowTime->Day = atoi(tempStr); + + strncpy(tempStr,P1+12+8,2); + pNowTime->Hour = atoi(tempStr); + + strncpy(tempStr,P1+12+10,2); + pNowTime->Min = atoi(tempStr); + + strncpy(tempStr,P1+12+12,2); + pNowTime->Sec = atoi(tempStr); + SLOGD("%d/%02d/%02d %02d:%02d:%02d\n",pNowTime->Year,pNowTime->Mon,pNowTime->Day,pNowTime->Hour,pNowTime->Min,pNowTime->Sec); + + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + else + { + callTime++; + if(callTime >600) + { + SLOGE("FAILED:send http timeout!!!!!\n"); + callTime = 0; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + + } + } + break; + case MODULE_HTTP_AUTHEN_AT_END: + if(strstr(ttyData, "OK") || (timeout_count > 100)) + return ret; + break; + default: + break; + } + + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("callTIme:%d, location:%d\n", callTime, enATcmdType); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enATcmdType); + timeout_count = 0; + return SF_HTTP_ERROR_AT_TIMEOUT; + } + } + return ret; + } + +SINT32 eg91_gps_Isupdate(SF_FN_PARAM_S *pfnParam,UINT8 *pIsupdate,SF_PARA_TIME_S *pNowTime,UINT8 u8day) +{ + + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + SF_COMM_CHECK_POINTER(pNowTime,SF_FAILURE); + + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT16 sts =1; + UINT16 timeout_count = 0; + UINT16 callTime = 0; + + SF_PARA_TIME_S preDate; + + SIM_SEARCH_GPS_e enMmcLocation = SIM_SEARCH_GPS_FIRST; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_GPS_ERROR_INS_EXIT; + } + + switch(enMmcLocation) + { + case SIM_SEARCH_GPS_FIRST: + sprintf(ttyData, "%s", "AT+QGPSXTRA?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_FIRST_1; + break; + case SIM_SEARCH_GPS_FIRST_1: + if(strstr(ttyData,"+QGPSXTRA: 1")) + { + sprintf(ttyData, "AT+QGPSXTRADATA?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_QGPSXTRA; + + } + else if(strstr(ttyData,"+QGPSXTRA: 0")) + { + callTime = 0; + sprintf(ttyData, "AT+QGPSXTRA=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_FIRST_2; + } + else if(timeout_count > 200) + { + enMmcLocation = SIM_SEARCH_GPS_EXIT; + + } + break; + case SIM_SEARCH_GPS_FIRST_2: + if(strstr(ttyData,"OK")) + { + sprintf(ttyData, "%s", "AT+QGPSXTRADATA?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_QGPSXTRA; + } + else + { + callTime++; + if(callTime > 10) + return SF_GPS_ERROR_AT_TIMEOUT; + } + break; + case SIM_SEARCH_GPS_QGPSXTRA: + if(strstr((const char *)ttyData,"OK")) + { + if(strstr(ttyData,",\"")!=NULL) + { + int diffsec = 0; + SF_CHAR *CCLK = strstr(ttyData, ",\""); + + preDate.Year = (CCLK[2]- '0')*1000 + (CCLK[3]- '0')*100 + (CCLK[4]-'0')*10 + (CCLK[5]-'0'); + preDate.Mon = (CCLK[7]- '0')*10 + (CCLK[8]- '0'); + preDate.Day = (CCLK[10]-'0')*10 + (CCLK[11]-'0'); + preDate.Hour = (CCLK[13]-'0')*10 + (CCLK[14]-'0'); + preDate.Min = (CCLK[16]-'0')*10 + (CCLK[17]-'0'); + preDate.Sec = (CCLK[19]-'0')*10 + (CCLK[20]-'0'); + + SLOGD("-[last update time:]-----%d/%d/%d %d:%d:%d\n", preDate.Year, preDate.Mon, preDate.Day, preDate.Hour, preDate.Min, preDate.Sec); + SLOGD("-[now update time:]-----%d/%d/%d %d:%d:%d\n", pNowTime->Year, pNowTime->Mon, pNowTime->Day, pNowTime->Hour, pNowTime->Min, pNowTime->Sec); + + diffsec = gps_diffSec_from_date(pNowTime, &preDate); + printf("------diffSec:%d--------------------------\n", diffsec); + + *pIsupdate = (diffsec < 0 || diffsec >(u8day*24*3600))?1:0; + + sts = 0; + return SF_SUCCESS; + + } + else + { + enMmcLocation = SIM_SEARCH_GPS_EXIT; + sprintf(ttyData, "AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + else + { + callTime++; + if(callTime > 10) + return SF_GPS_ERROR_AT_TIMEOUT; + } + break; + case SIM_SEARCH_GPS_EXIT: + sts = 0; + return SF_GPS_ERROR_NOT_MATCH; + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("callTIme:%d, location:%d\n", callTime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enMmcLocation); + timeout_count = 0; + return SF_GPS_ERROR_AT_TIMEOUT; + } + } + return SF_SUCCESS; +} + + +SINT32 eg91_gps_search(SF_FN_PARAM_S *pfnParam,SF_PARA_TIME_S *pNowTime,UINT8 autoModeFlag) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + SF_COMM_CHECK_POINTER(pNowTime,SF_FAILURE); + UINT16 timeout_count = 0; + UINT16 callTime = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT16 sts =1; + UINT16 calltime = 0; + UINT8 pdpdeact = 0; + SINT16 ret = SF_FAILURE; + + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + SIM_SEARCH_GPS_e enMmcLocation = SIM_SEARCH_GPS_FIRST; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_GPS_ERROR_INS_EXIT; + } + + switch(enMmcLocation) + { + case SIM_SEARCH_GPS_FIRST: + enMmcLocation = SIM_SEARCH_GPS_DELRAM; + sprintf(ttyData, "AT+QFDEL=\"RAM:*\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_SEARCH_GPS_DELRAM: + if(strstr(ttyData,"OK") || strstr(ttyData,"ERROR")) + { + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + { + sprintf(ttyData, "AT+QHTTPCFG=\"contextid\",%d\r", V_PDP_INDEX); + } + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + { + sprintf(ttyData, "AT+QHTTPCFG=\"contextid\",%d\r", A_PDP_INDEX); + } + else + { + sprintf(ttyData, "AT+QHTTPCFG=\"contextid\",%d\r", E_PDP_INDEX); + } + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_REQUESTHEADER; + } + break; + case SIM_SEARCH_GPS_REQUESTHEADER: + sprintf(ttyData, "AT+QHTTPCFG=\"requestheader\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD1; + break; + case SIM_SEARCH_GPS_DOWNLOAD1: + sprintf(ttyData, "AT+QHTTPCFG=\"responseheader\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD2; + break; + + case SIM_SEARCH_GPS_DOWNLOAD2: + + SLOGD("APN:%s \n", pStaticParam->ApnGPRS); + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + { + sprintf(ttyData, "AT+QICSGP=%d\r", V_PDP_INDEX); + enMmcLocation = SIM_SEARCH_GPS_CSGP; + } + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + { + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", A_PDP_INDEX, + pStaticParam->ApnGPRS, pStaticParam->ApnUsername, pStaticParam->ApnPassword); + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD3;; + } + else + { + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", E_PDP_INDEX, + pStaticParam->ApnGPRS, pStaticParam->ApnUsername, pStaticParam->ApnPassword); + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD3; + } + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + + case SIM_SEARCH_GPS_CSGP: + if(strstr(ttyData, "OK")) + { + if(strstr(ttyData, "+QICSGP: 0") || strstr(ttyData, "+QICSGP: 1,\"\"")) + { + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r",V_PDP_INDEX, + pStaticParam->ApnGPRS, pStaticParam->ApnUsername, pStaticParam->ApnPassword); + } + else + { + sprintf(ttyData, "AT\r"); + } + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD3; + } + break; + + case SIM_SEARCH_GPS_DOWNLOAD3: + if(strstr(ttyData, "OK")) + { + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + sprintf(ttyData, "AT+QIACT=%d\r", V_PDP_INDEX); + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + sprintf(ttyData, "AT+QIACT=%d\r", A_PDP_INDEX); + else + sprintf(ttyData, "AT+QIACT=%d\r", E_PDP_INDEX); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD4; + + } + break; + + case SIM_SEARCH_GPS_DOWNLOAD4: + if(strstr(ttyData, "OK")) + { + int len=0; + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD5; + len = strlen("http://xtrapath3.izatcloud.net/xtra3grc.bin"); + sprintf(ttyData, "AT+QHTTPURL=%d,80\r", len); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else if(strstr(ttyData,"ERROR")) + { + calltime++; + SLOGD("calltime++=%d\n",calltime); + if(calltime<6) + { + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + sprintf(ttyData, "AT+QIACT=%d\r", V_PDP_INDEX); + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + sprintf(ttyData, "AT+QIACT=%d\r", A_PDP_INDEX); + else + sprintf(ttyData, "AT+QIACT=%d\r", E_PDP_INDEX); + + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(1700); + } + else + { + SLOGE("[ERROR]GPS AT+QIACT over try 6 times\n"); + calltime = 0; + sts = 0; + ret = SF_GPS_ERROR_QIACT; + } + } + break; + + case SIM_SEARCH_GPS_DOWNLOAD5: + if(strstr(ttyData, "CONNECT")) + { + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD6; + sprintf(ttyData, "http://xtrapath3.izatcloud.net/xtra3grc.bin\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + case SIM_SEARCH_GPS_DOWNLOAD6: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD7; + sprintf(ttyData, "AT+QHTTPGET=80\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_SEARCH_GPS_DOWNLOAD7: + if(strstr(ttyData, "+QHTTPGET: 0,200")) + { + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD8; + sprintf(ttyData, "AT+QHTTPREADFILE=\"RAM:xtra2.bin\",80\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + calltime++; + printf("calltime=%d\n",calltime); + if(calltime > 50) + { + calltime = 0; + enMmcLocation = SIM_SEARCH_GPS_EXIT; + SLOGE("[ERROR]GPS QHTTPGET time out\n"); + + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + sprintf(ttyData, "AT+QIDEACT=%d\r", V_PDP_INDEX); + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + sprintf(ttyData, "AT+QIDEACT=%d\r", A_PDP_INDEX); + else + sprintf(ttyData, "AT+QIDEACT=%d\r", E_PDP_INDEX); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + break; + case SIM_SEARCH_GPS_DOWNLOAD8: + if(strstr(ttyData,"+QHTTPREADFILE: 0")) + { + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD10; + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + sprintf(ttyData, "AT+QIDEACT=%d\r", V_PDP_INDEX); + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + sprintf(ttyData, "AT+QIDEACT=%d\r", A_PDP_INDEX); + else + sprintf(ttyData, "AT+QIDEACT=%d\r", E_PDP_INDEX); + + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(ttyData,"+QHTTPREADFILE: 702") != NULL) + { + enMmcLocation = SIM_SEARCH_GPS_EXIT; + SLOGE("[ERROR]GPS +QHTTPREADFILE: 702\n"); + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + sprintf(ttyData, "AT+QIDEACT=%d\r", V_PDP_INDEX); + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + sprintf(ttyData, "AT+QIDEACT=%d\r", A_PDP_INDEX); + else + sprintf(ttyData, "AT+QIDEACT=%d\r", E_PDP_INDEX); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + case SIM_SEARCH_GPS_DOWNLOAD9: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_SEARCH_GPS_DOWNLOAD10; + sprintf(ttyData, "AT+QGPSXTRA=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + case SIM_SEARCH_GPS_DOWNLOAD10: + if(strstr(ttyData,"OK")) + { + enMmcLocation = SIM_SEARCH_GPS_GPS_XTRADATA2; + sprintf(ttyData, "AT+QGPSXTRATIME=0,\"%04d/%02d/%02d,%02d:%02d:%02d\",1,1,5\r", + pNowTime->Year, pNowTime->Mon, pNowTime->Day, pNowTime->Hour, pNowTime->Min, pNowTime->Sec); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_SEARCH_GPS_GPS_XTRADATA1: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_SEARCH_GPS_GPS_XTRADATA2; + sprintf(ttyData, "AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(ttyData, "+QGPSURC") != 0 ) + { + printf("SIYUAN:qrc"); + enMmcLocation = SIM_SEARCH_GPS_GPS_XTRADATA2; + sprintf(ttyData, "AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + + } + break; + + case SIM_SEARCH_GPS_GPS_XTRADATA2: + if(strstr(ttyData, "OK")) + { + + enMmcLocation = SIM_SEARCH_GPS_EXIT; + sprintf(ttyData, "AT+QGPSXTRADATA=\"RAM:xtra2.bin\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_SEARCH_GPS_ON: + enMmcLocation = SIM_SEARCH_GPS_EXIT; + sprintf(ttyData, "AT+QGPS=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_SEARCH_GPS_EXIT: + sts = 0; + return SF_SUCCESS; + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("callTIme:%d, location:%d\n", callTime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enMmcLocation); + timeout_count = 0; + return SF_GPS_ERROR_AT_TIMEOUT; + } + } + return ret; +} +SINT32 eg91_gps_preconfig(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + + UINT16 timeout_count = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT16 sts =1; + UINT16 calltime = 0; + UINT8 pdpdeact = 0; + UINT8 sendTryTime = 0; + SINT16 ret = SF_FAILURE; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + SIM_SEARCH_GPS_e enMmcLocation = SIM_SEARCH_GPS_FIRST; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_GPS_ERROR_INS_EXIT; + } + + switch(enMmcLocation) + { + case SIM_SEARCH_GPS_FIRST: + enMmcLocation = SIM_SEARCH_GPS_ON; + sprintf(ttyData, "%s", "AT+QGPSCFG=\"outport\",\"uartdebug\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_SEARCH_GPS_ON: + enMmcLocation = SIM_SEARCH_GPS_EXIT; + sprintf(ttyData, "AT+QGPS=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + + case SIM_SEARCH_GPS_LOC: + if(strstr(ttyData,"OK")) + { + enMmcLocation = SIM_SEARCH_GPS_END; + sprintf(ttyData, "AT+QGPSLOC=2\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + calltime = 0; + } + else if(strstr(ttyData, "ERROR")) + { + if(sendTryTime == 0) + { + calltime = 0; + sendTryTime++; + enMmcLocation = SIM_SEARCH_GPS_ON; + sprintf(ttyData, "AT+QGPSEND\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SLOGE("[ERROR] GPS ON ERR, Try:%d\n", sendTryTime); + } + else + { + calltime = 0; + sendTryTime = 0; + enMmcLocation = SIM_SEARCH_GPS_EXIT; + sprintf(ttyData, "AT+QGPSEND\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SLOGE("[ERROR] GPS ON ERR\n"); + } + } + break; + + case SIM_SEARCH_GPS_END: + if(strstr(ttyData, "ERROR") != 0) + { + //3minite timeout. + if(calltime > GPS_SEARCH_TIMEOUT_TIMES) + { + calltime = 0; + enMmcLocation = SIM_SEARCH_GPS_EXIT; + pStaticParam->DialyReportFailCnt++; + sprintf(ttyData, "AT+QGPSEND\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SLOGE("[ERROR] GPS timeout\n"); + sts = 0; + ret = SF_GPS_ERROR_AT_TIMEOUT; + } + else + { + sprintf(ttyData, "AT+QGPSLOC=2\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + calltime++; + sf_sleep_ms(100); + + } + else if(strstr(ttyData, "+QGPSLOC:") != 0) + { + printf("--------Loc:----------------------\n"); + + SF_CHAR *str=NULL; + strtok(ttyData,","); + str = strtok(NULL,","); + if(NULL!=str) + { + strcpy(pStaticParam->Latitude,str); + //sf_gps_infor_convert(&sim_info_t->Latitude[5]); + } + str = strtok(NULL,","); + if(NULL!=str) + { + strcpy(pStaticParam->Longitude,str); + //sf_gps_infor_convert(&sim_info_t->Longitude[6]); + } + + //sf_set_netsearch_step(SIM_NETSEARCH_STEP_GPS); + pStaticParam->DialyReportFailCnt = 0; + + enMmcLocation = SIM_SEARCH_GPS_EXIT; + calltime = 0; + sprintf(ttyData, "AT+QGPSEND\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + printf("SIYUAN-Bob:latitude=%s,longitude=%s\n", pStaticParam->Latitude, pStaticParam->Longitude); + } + break; + case SIM_SEARCH_GPS_EXIT: + sts = 0; + if(pdpdeact) + { + pdpdeact = 0; + //sf_pdp_flg_set(0); + } + return SF_SUCCESS; + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("callTIme:%d, location:%d\n", calltime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enMmcLocation); + timeout_count = 0; + return SF_GPS_ERROR_AT_TIMEOUT; + } + } + return ret; +} + +SINT32 eg91_gps_search_result(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + + UINT16 timeout_count = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT16 sts =1; + UINT16 calltime = 0; + UINT8 pdpdeact = 0; + UINT8 sendTryTime = 0; + SINT16 ret = SF_SUCCESS; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + SIM_SEARCH_GPS_e enMmcLocation = SIM_SEARCH_GPS_LOC; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_GPS_ERROR_INS_EXIT; + } + + switch(enMmcLocation) + { + case SIM_SEARCH_GPS_ON: + enMmcLocation = SIM_SEARCH_GPS_LOC; + sprintf(ttyData, "AT+QGPS=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_SEARCH_GPS_LOC: + + #ifndef SF_GPS_TEST + enMmcLocation = SIM_SEARCH_GPS_END; + #endif + sprintf(ttyData, "AT+QGPSLOC?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + #ifdef SF_GPS_TEST + calltime++; + #else + calltime = 0; + #endif + break; + case SIM_SEARCH_GPS_END: + if(strstr(ttyData, "ERROR") != 0) + { + + if(calltime > GPS_SEARCH_TIMEOUT_TIMES) + { + calltime = 0; + enMmcLocation = SIM_SEARCH_GPS_EXIT; + pStaticParam->DialyReportFailCnt++; + + sprintf(ttyData, "AT+QGPSEND\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SLOGE("[ERROR] GPS timeout\n"); + ret = SF_GPS_ERROR_AT_TIMEOUT; + } + else + { + sprintf(ttyData, "AT+QGPSLOC?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + calltime++; + sf_sleep_ms(100); + + } + else if(strstr(ttyData, "+QGPSLOC:") != 0) + { + + SF_CHAR *str=NULL; + strtok(ttyData,","); + str = strtok(NULL,","); + if(NULL!=str) + { + strcpy(pStaticParam->Latitude,str); + gps_infor_convert(&pStaticParam->Latitude[5]); + } + str = strtok(NULL,","); + if(NULL!=str) + { + strcpy(pStaticParam->Longitude,str); + gps_infor_convert(&pStaticParam->Longitude[6]); + } + + + enMmcLocation = SIM_SEARCH_GPS_EXIT; + calltime = 0; + sprintf(ttyData, "AT+QGPSEND\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + printf("SIYUAN-Bob:latitude=%s,longitude=%s\n", pStaticParam->Latitude, pStaticParam->Longitude); + } + break; + case SIM_SEARCH_GPS_EXIT: + sts = 0; + return SF_SUCCESS; + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("callTIme:%d, location:%d\n", calltime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + #ifndef SF_GPS_TEST + timeout_count++; + #endif + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enMmcLocation); + timeout_count = 0; + return SF_GPS_ERROR_AT_TIMEOUT; + } + } + return ret; +} + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + diff --git a/code/application/source/sf_app/code/source/4gMng/sf_eg91_server.c b/code/application/source/sf_app/code/source/4gMng/sf_eg91_server.c new file mode 100755 index 000000000..8c0a66715 --- /dev/null +++ b/code/application/source/sf_app/code/source/4gMng/sf_eg91_server.c @@ -0,0 +1,1451 @@ +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#include "sf_log.h" + +#include "sf_hal_ttyusb.h" +#include "sf_opera_adapt.h" +#include "sf_param_common.h" +#include "sf_eg91_server.h" +#include "sf_dataMng.h" +#include "cJSON.h" +#include "sf_base64.h" +SINT32 eg91_file_to_module(SF_CHAR *fileName, SINT32 *fileSize, SF_FILE_TYPE_E fileType) +{ + SF_COMM_CHECK_POINTER(fileName,SF_FAILURE); + SF_COMM_CHECK_POINTER(fileSize,SF_FAILURE); + + SINT32 fileFd = 0; + SINT32 tolFileSize = 0; + SINT32 readSize = 0; + UINT16 count = 0; + SINT16 ret = SF_SUCCESS; + SINT16 ret1 = SF_SUCCESS; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR tempFileName[32] = { 0 }; + SF_CHAR *pBuf = NULL; + SF_CHAR *bufBak = NULL; + struct stat statBuf; + + SLOGD("fileName:%s type: %d,filename :%d \n",fileName,fileType,strlen(fileName)); + + sprintf(ttyData, "AT+QFDEL=\"*\"\r"); + + ret1 = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + + sf_hal_ttyusb2_read(ttyData, 150); + SLOGD("filename:%s\n", fileName); + + fileFd = open(fileName, O_RDONLY); + + if(fileFd) + { + fstat(fileFd, &statBuf); + tolFileSize = statBuf.st_size; + *fileSize = tolFileSize; + SLOGD("tolFileSize:%d\n", *fileSize); + + if(tolFileSize > 1024*1024*5) + { + bufBak = malloc(1024*1024*5); + } + else + { + bufBak = malloc(tolFileSize); + } + + if(bufBak) + { + if(fileType == SF_FILE_TYPE_PIC_BIG) + memcpy(tempFileName, fileName + (strlen(fileName) - SF_PIC_NAME_LEN), SF_PIC_NAME_LEN); + else if(fileType == SF_FILE_TYPE_PIC_SMALL ||fileType == SF_FILE_TYPE_PIC_VIDEO) + memcpy(tempFileName, fileName + (strlen(fileName) - SF_PIC_NAME_LEN), SF_PIC_NAME_LEN); + else if(fileType == SF_FILE_TYPE_VIDEO) + memcpy(tempFileName, fileName + (strlen(fileName) - SF_PIC_NAME_LEN), SF_PIC_NAME_LEN); + else if(fileType == SF_FILE_TYPE_LOG_ERROR) + memcpy(tempFileName, fileName + (strlen(fileName) - ERROR_LOG_NAME_LEN), ERROR_LOG_NAME_LEN); + else if(fileType == SF_FILE_TYPE_GPS) + memcpy(tempFileName, fileName + (strlen(fileName) - GPS_LOG_NAME_LEN), GPS_LOG_NAME_LEN); + else if(fileType == SF_FILE_TYPE_BT_ALARM) + memcpy(tempFileName, fileName + (strlen(fileName) - BT_ALARM_NAME_LEN), BT_ALARM_NAME_LEN); + else if(fileType == SF_FILE_TYPE_FOTA) + strcpy(tempFileName,OTA_FTP_UPDATAFILENAME); + else + memcpy(tempFileName, fileName + (strlen(fileName) - 15), 15); + + SLOGD("tempFileName:%s\n", tempFileName); + sprintf(ttyData, "AT+QFUPL=\"%s\",%d\r", tempFileName, tolFileSize); + SLOGD("sendbuf:%s\n", ttyData); + + ret1 = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ret1, ret1); + sf_hal_ttyusb2_read(ttyData, 200); + + while(count < 15) + { + count++; + SLOGD("ttyData:%s\n", ttyData); + + if(strstr(ttyData,"+CME ERROR")) + { + SLOGE("recv error!\n"); + ret = SF_4G_ERROR_AT_READ; + break; + } + else if(strstr(ttyData,"CONNECT")) + { + //MLOGD("read file\n"); + while(tolFileSize > 0) + { + pBuf = bufBak; + if(tolFileSize >= 1024*1024*5) + readSize = read(fileFd, pBuf, 1024*1024*5); + else + readSize = read(fileFd, pBuf, tolFileSize); + + SLOGD("send file data, tolFileSize:%d, read size:%d\n", tolFileSize, readSize); + tolFileSize -= readSize; + + + while(readSize > 0) + { + if(readSize > 10240) + { + //sf_hal_ttyusb2_write(fd, pBuf, 10240); + ret1 = sf_hal_ttyusb2_write(pBuf, 10240); + SF_APPCOMM_CHECK_RETURN(ret1, ret1); + + readSize -= 10240; + pBuf += 10240; + } + else + { + //sf_hal_ttyusb2_write(fd, pBuf, readSize); + ret1 = sf_hal_ttyusb2_write(pBuf, readSize); + SF_APPCOMM_CHECK_RETURN(ret1, ret1); + pBuf += readSize; + readSize = 0; + } + sf_sleep_ms(1); + } + } + + sf_hal_ttyusb2_read(ttyData, 300); + SLOGD("ttyData:%s\n", ttyData); + + if((strstr(ttyData,"+QFUPL:"))) + { + //nothing to do + } + else + { + sf_hal_ttyusb2_read(ttyData, 300); + } + SLOGD("send end\n"); + SLOGD("send end\n"); + break; + } + else + { + sf_hal_ttyusb2_read(ttyData, 300); + } + } + + SLOGD("\n"); + free(bufBak); + close(fileFd); + } + else + { + SLOGE("malloc buf fail!\n"); + close(fileFd); + ret = SF_4G_ERROR_FILE_SEND; + } + } + else + { + SLOGE("open file error!\n"); + } + + SLOGD("\n"); + return ret; + } + +static SINT16 eg91_ip_get(cJSON *object, SF_CHAR *webIP, SF_CHAR *acmIP) +{ + SF_CHAR tempStr[128] = {0}; + SF_CHAR decode_tempStr[128] = {0}; + UINT8 type = 0; + + type = cJSON_GetObjectItem(object,"serverType")->valueSINT32; + sprintf(tempStr,"%s",cJSON_GetObjectItem(object,"ip")->valuestring); + printf("type:%d,ip:%s\n",type,tempStr); + + sf_base64_decode(tempStr,decode_tempStr); + printf("decode_tempStr=%s\n",decode_tempStr); + if(SF_NULL == strlen(decode_tempStr)) + return SF_FAILURE; + + if(type == 1) + { + sprintf(webIP,"%s",decode_tempStr); + } + else if(type == 2) + { + sprintf(acmIP,"%s",decode_tempStr); + } + else + { + memset(acmIP, '\0', strlen(acmIP)); + memset(acmIP, '\0', strlen(acmIP)); + return SF_FAILURE; + } + return SF_SUCCESS; + +} +static SINT16 eg91_parse_server_get(SF_CHAR *buf, SF_CHAR *webIp, SF_CHAR *acmIp) + { + SF_COMM_CHECK_POINTER(buf,SF_FAILURE); + SF_COMM_CHECK_POINTER(webIp,SF_FAILURE); + SF_COMM_CHECK_POINTER(acmIp,SF_FAILURE); + + cJSON_Hooks hooks = {malloc, free}; + + UINT8 statu[5] = {1}; + UINT8 msg[10] = {0}; + SINT16 errorcode = SF_SUCCESS; + + cJSON_InitHooks(&hooks); + cJSON *root = cJSON_Parse(buf); + + sprintf((SF_CHAR*)statu,"%s",cJSON_GetObjectItem(root,"statu")->valuestring); + errorcode = cJSON_GetObjectItem(root,"errCode")->valueSINT32; + printf("statu=%s\n",statu); + printf("errCode=%d\n",errorcode); + if(!strstr(buf,"null")) + { + cJSON *content = cJSON_GetObjectItem(root,"content");/**/ + cJSON *object1 = cJSON_GetArrayItem(content,0); + cJSON *object2 = cJSON_GetArrayItem(content,1); + eg91_ip_get(object1, webIp, acmIp); + eg91_ip_get(object2, webIp, acmIp); + } + + cJSON_Delete(root); + + printf("webIp=%s\n",webIp); + printf("acmIp=%s\n",acmIp); + printf("ret=%d\n",errorcode); + return errorcode; + + } + + UINT32 eg91_parse_server_get_time(UINT8 *buf) + { + SF_COMM_CHECK_POINTER(buf,SF_FAILURE); + cJSON_Hooks hooks = {malloc, free}; + + UINT8 statu[10] = {0}; + UINT32 errCode = 0; + + cJSON_InitHooks(&hooks); + + printf("dest_buf = %s\n", buf); + cJSON *root = cJSON_Parse((SF_CHAR*)buf); + + sprintf((SF_CHAR*)statu,"%s",cJSON_GetObjectItem(root,"statu")->valuestring); + + errCode = cJSON_GetObjectItem(root,"errCode")->valueSINT32; + printf("statu=%s\n",statu); + printf("errCode=%d\n",errCode); + if(strstr((SF_CHAR*)buf,"null")) + { + + } + else + { + cJSON *content = cJSON_GetObjectItem(root, "content");/**/ + printf("%s,%d\n", __FUNCTION__, __LINE__); + sprintf((SF_CHAR*)buf, "%s", cJSON_GetObjectItem(content,"greenDate")->valuestring); + printf("buf:%s\n", buf); + //cJSON_Delete(content); + } + cJSON_Delete(root); + + return errCode; + + } + +SINT32 eg91_http_config(SF_FN_PARAM_S *pfnParam, UINT8 sslOn, UINT8 autoReqHead) + { + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + SINT32 ttyRet = SF_SUCCESS; + SINT32 ret = SF_SUCCESS; + UINT16 timeout_count = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + MODULE_HTTP_CONFIG_E enATcmdType = MODULE_HTTP_CONFIG_AT_QICSGP; + SF_PDT_PARAM_STATISTICS_S *pstParamInfo = pfnParam->pstaticParam; + + + while(1) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch(enATcmdType) + { + case MODULE_HTTP_CONFIG_AT_ATW: + sprintf(ttyData,"%s","AT&W\r"); + enATcmdType = MODULE_HTTP_CONFIG_AT_QICSGP; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_HTTP_CONFIG_AT_QICSGP: + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", HTTP_PDP, pstParamInfo->ApnGPRS, pstParamInfo->ApnUsername, pstParamInfo->ApnPassword); + enATcmdType = MODULE_HTTP_CONFIG_AT_QHTTPCFG_1; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_HTTP_CONFIG_AT_QHTTPCFG_1: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + sprintf(ttyData, "AT+QHTTPCFG=\"contextid\",%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_CONFIG_AT_QHTTPCFG_2; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(strstr(ttyData, "ERROR")) + { + return SF_4G_ERROR_AT_APN; + } + break; + + case MODULE_HTTP_CONFIG_AT_QHTTPCFG_2: + if(strstr(ttyData, "OK")) + { + if(sslOn) + enATcmdType = MODULE_HTTP_CONFIG_AT_QHTTPCFG_3; + else + enATcmdType = MODULE_HTTP_CONFIG_AT_END; + + timeout_count = 0; + if(autoReqHead) + sprintf(ttyData,"AT+QHTTPCFG=\"requestheader\",0\r"); + else + sprintf(ttyData,"AT+QHTTPCFG=\"requestheader\",1\r"); + + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_CONFIG_AT_QHTTPCFG_3: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + sprintf(ttyData,"%s", "AT+QHTTPCFG=\"sslctxid\",1\r"); + enATcmdType = MODULE_HTTP_CONFIG_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_CONFIG_AT_QSSLCFG_1: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + sprintf(ttyData,"%s","AT+QSSLCFG=\"sslversion\",1,4\r"); + enATcmdType = MODULE_HTTP_CONFIG_AT_QSSLCFG_2; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_CONFIG_AT_QSSLCFG_2: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + sprintf(ttyData,"%s","AT+QSSLCFG=\"ciphersuite\",1,0XFFFF\r"); + enATcmdType = MODULE_HTTP_CONFIG_AT_QSSLCFG_3; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_CONFIG_AT_QSSLCFG_3: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + enATcmdType = MODULE_HTTP_CONFIG_AT_END; + sprintf(ttyData,"%s","AT+QSSLCFG=\"seclevel\",1,0\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_CONFIG_AT_END: + if(strstr(ttyData, "OK")) + return SF_SUCCESS; + break; + + default: + break; + } + + SLOGD("sendBuf******\n %s \n*********************\n\n",ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + MLOGI("timeout_count:%d, location:%d\n", timeout_count, enATcmdType); + SLOGD("revBuf******\n %s \n*********************\n\n",ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]AT timeout, enATcmdType=%d\n", enATcmdType); + return SF_4G_ERROR_AT_TIMEOUT; + } + } + + return ret; + } + + SINT32 eg91_http_authenrequst(SF_FN_PARAM_S *pfnParam) + { + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + SINT32 ttyRet = SF_SUCCESS; + SINT32 ret = SF_SUCCESS; + SINT32 errorcode = 0; + SINT16 sts = 1; + UINT16 timeout_count = 0; + UINT16 callTime = 0; + UINT8 reHttpSRequest=0; + UINT8 authenrequstCnt = 0; + SF_CHAR *P1 = NULL; + SF_CHAR *P2 = NULL; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR dataStr[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR webStr[40] = {0}; + SF_CHAR acmStr[40] = {0}; + MODULE_SERVER_AUTHEN_E enATcmdType = MODULE_HTTP_AUTHEN_AT_QIACT; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam;/* Added by MaxLi 2022/03/02--15:5:56*/ + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch(enATcmdType) + { + case MODULE_HTTP_AUTHEN_AT_QIACT: + sprintf(ttyData,"AT+QIACT=%d\r",HTTP_PDP);/**/ + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPURL_1: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + sprintf(dataStr,"https://%s/device/imeiAndMSisdn?imei=%s&iccid=%s", pStaticParam->WebIP, pStaticParam->IMEI, pStaticParam->SimID); + sprintf(ttyData, "AT+QHTTPURL=%d,80\r",strlen(dataStr)); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_2; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(strstr(ttyData, "ERROR")) + { + callTime++; + if(callTime < PDP_TRY_TIME) + { + sf_sleep_s(2); + sprintf(ttyData, "AT+QIACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + callTime=0; + sts = 0; + ret = SF_4G_ERROR_AT_ACTIVE; + SLOGE("Moudle QIACT ERROR.DATA:%s", ttyData); + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + + + } + } + else if(timeout_count > 100) + { + sts = 0; + ret = SF_4G_ERROR_AT_ACTIVE; + SLOGE("Moudle QIACT timeout"); + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPURL_2: + if(strstr(ttyData, "CONNECT")) + { + timeout_count = 0; + sprintf(ttyData,"https://%s/device/imeiAndMSisdn?imei=%s&iccid=%s", pStaticParam->WebIP, pStaticParam->IMEI, pStaticParam->SimID); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPGET; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPGET: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + sprintf(ttyData,"%s","AT+QHTTPGET=80\r"); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPREAD; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_HTTP_AUTHEN_AT_QHTTPREAD: + timeout_count = 0; + callTime++; + if(strstr(ttyData, "+QHTTPGET:")) + { + if(strstr(ttyData, "+QHTTPGET: 0,200")) + { + timeout_count= 0; + callTime = 0; + sprintf(ttyData,"%s","AT+QHTTPREAD=80\r"); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QIDEACT; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(reHttpSRequest == 0) + { + SLOGW("HTTP Send Failed,try again\n"); + + reHttpSRequest = 1; + sprintf(ttyData,"%s","AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + } + else + { + SLOGE("HTTP Send Failed,data:%s\n", ttyData); + SLOGE("FAILED:send http failed!!!!!\n"); + + ret = SF_HTTP_ERROR_REQUEST; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + } + } + else + { + if((strstr(ttyData,"ERROR")) || (callTime > 400)) + { + if(reHttpSRequest == 0) + { + SLOGW("HTTP Send timeout,try again\n"); + reHttpSRequest = 1; + sprintf(ttyData,"%s","AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + } + else + { + SLOGW("HTTP Send timeout,data:%s", ttyData); + MLOGW("FAILED:send http timeout!!!!!\n"); + ret = SF_HTTP_ERROR_REQUEST; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + } + } + + } + + break; + + case MODULE_HTTP_AUTHEN_AT_QIDEACT: + timeout_count = 0; + P1 = strstr(ttyData, "OK"); + if(P1) + { + memset(dataStr,'\0', sizeof(dataStr)); + + P2 = strstr(ttyData,"{"); + if(P2 != NULL) + { + strncpy(dataStr, P2, P1-P2); + errorcode = eg91_parse_server_get(dataStr, webStr, acmStr); + } + if((errorcode == SF_SUCCESS) && (webStr[0] != '\0') && (acmStr[0] != '\0')) + { + if(authenrequstCnt < 6) + { + + sprintf(pStaticParam->WebIP, "%s", webStr); + memset(pStaticParam->AcmIP,'\0', sizeof(pStaticParam->AcmIP)); + sprintf(pStaticParam->AcmIP, "%s", acmStr); + + memset(webStr,'\0', sizeof(webStr)); + memset(acmStr,'\0', sizeof(acmStr)); + + reHttpSRequest = 0; + authenrequstCnt++; + enATcmdType = MODULE_HTTP_AUTHEN_AT_QHTTPURL_1; + sprintf(ttyData, "AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + ret = SF_HTTP_ERROR_AT_TIMEOUT; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + else + { + if(errorcode == 30004) + ret = SF_4G_ERROR_NO_SUPPOET; + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + /*else if(callTime > 400) + { + SLOGD("HTTP Read timeout,data:%s", ttyData); + MLOGD("FAILED:send http timeout!!!!!\n"); + callTime = 0; + sts = 0; + ret = SF_HTTP_ERROR_READ; + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + }*/ + else + { + if(callTime < 5) + { + sprintf(ttyData,"%s","AT+QHTTPREAD=80\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else + { + callTime = 0; + sts = 0; + ret = SF_HTTP_ERROR_AT_READ; + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_HTTP_AUTHEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + } + callTime++; + break; + + case MODULE_HTTP_AUTHEN_AT_END: + if(strstr(ttyData, "OK") || (timeout_count > 100)) + return ret; + break; + + default: + break; + } + SLOGI("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + MLOGI("callTIme:%d, location:%d\n", callTime, enATcmdType); + SLOGI("revBuf******\n %s \n*********************\n\n", ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enATcmdType); + timeout_count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + } + + return ret; + } + + SINT32 eg91_http_pushfile(SF_FILE_ATTR_S *pstFileAttr,SF_FN_PARAM_S *pfnParam) + { + SF_COMM_CHECK_POINTER(pstFileAttr,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstFileAttr->txtfileName,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + SINT32 ttyRet = SF_SUCCESS; + SINT32 ret = SF_SUCCESS; + // SINT16 sts = 1; + UINT16 timeout_count = 0; + UINT8 reHttpSRequest = 0; + UINT16 callTime = 0; + UINT8 sendfailedcnt = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR tempIP[128] = { 0 }; + + MODULE_SERVER_SENDFILE_E enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPCFG; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + while(1) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + switch(enATcmdType) + { + + case MODULE_SERVER_SENDFILE_AT_QHTTPCFG: + sprintf(ttyData, "AT+QIACT=%d\r", HTTP_PDP);/**/ + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPURL_1; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_SERVER_SENDFILE_AT_QHTTPURL_1: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + if(sf_data_transfer_mode_get() == SF_UPLOAD_OSS) + { + sprintf(tempIP, "http://%s", pStaticParam->stOssCfg.szIP); + sprintf(ttyData, "AT+QHTTPURL=%d,80\r", strlen(tempIP)); + + } + else + { + sprintf(tempIP, "http://%s.%s", pStaticParam->stOssCfg.szBucket, AMZ_HOST); + sprintf(ttyData, "AT+QHTTPURL=%d,80\r", strlen(tempIP)); + } + + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPURL_2; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(strstr(ttyData, "ERROR")) + { + callTime++; + if(callTime < PDP_TRY_TIME) + { + sf_sleep_s(2); + sprintf(ttyData, "AT+QIACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + callTime=0; + ret = SF_4G_ERROR_AT_ACTIVE; + SLOGD("Moudle QIACT ERROR.DATA:%s", ttyData); + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + + + } + } + else if(timeout_count > 100) + { + ret = SF_4G_ERROR_AT_ACTIVE; + SLOGD("Moudle QIACT timeout"); + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_SENDFILE_AT_QHTTPURL_2: + if(strstr(ttyData, "CONNECT")) + { + timeout_count = 0; + sprintf(ttyData,"%s\r", tempIP); + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPPOSTFILE; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_SENDFILE_AT_QHTTPPOSTFILE: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + sprintf(ttyData, "AT+QHTTPPOSTFILE=\"%s\",80\r", pstFileAttr->txtfileName); + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTREAD; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_SENDFILE_AT_QHTTREAD: + timeout_count = 0; + if((strstr(ttyData, "+QHTTPPOSTFILE:")) || (strstr(ttyData,",200,"))) + { + if((strstr(ttyData,",200,"))) + { + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_SERVER_SENDFILE_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if((strstr(ttyData,"400")) || (strstr(ttyData,"403"))) + { + sendfailedcnt++; + if(sendfailedcnt > 1) + { + callTime = 0; + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_SERVER_SENDFILE_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sendfailedcnt= 0; + ret = SF_HTTP_ERROR_FILE_SEND; + } + else + { + callTime = 0; + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPCFG; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + + } + else + { + if(reHttpSRequest == 0) + { + reHttpSRequest = 1; + printf("FAILED:send http file failed,try again!!!!!\n"); + SLOGD("HTTP Send OSS Failed,try again."); + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPPOSTFILE; + strcpy(ttyData, "AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + SLOGD("HTTP Send File Failed."); + printf("FAILED:send http file failed!!!!!\n"); + enATcmdType = MODULE_SERVER_SENDFILE_AT_END_1; + ret = SF_HTTP_ERROR_FILE_SEND; + sprintf(ttyData, "AT+QIDEACT=%d\r",HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + } + else if(callTime > 400) + { + if(reHttpSRequest == 0) + { + reHttpSRequest = 1; + printf("FAILED:send http file timeout,try again!!!!!\n"); + SLOGD("HTTP Send OSS timeout,try again."); + enATcmdType = MODULE_SERVER_SENDFILE_AT_QHTTPPOSTFILE; + strcpy(ttyData, "AT\r"); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + SLOGD("HTTP Send File timeout."); + printf("FAILED:send http file timeout!!!!!\n"); + callTime = 0; + ret = SF_HTTP_ERROR_FILE_SEND; + enATcmdType = MODULE_SERVER_SENDFILE_AT_END; + sprintf(ttyData, "AT+QIDEACT=%d\r", HTTP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + callTime++; + break; + case MODULE_SERVER_SENDFILE_AT_END_1: + timeout_count = 0; + if(strstr(ttyData, "OK")) + { + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_SERVER_SENDFILE_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(callTime > 400) + { + SLOGD("HTTP Read timeout,data:%s", ttyData); + MLOGD("FAILED:send http timeout!!!!!\n"); + callTime = 0; + ret = SF_HTTP_ERROR_AT_READ; + sprintf(ttyData,"AT+QIDEACT=%d\r",HTTP_PDP); + enATcmdType = MODULE_SERVER_SENDFILE_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + callTime++; + break; + + case MODULE_SERVER_SENDFILE_AT_END: + if(strstr(ttyData, "OK") || (timeout_count > 100)) + return ret; + break; + + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n",ttyData); + + sf_hal_ttyusb2_read(ttyData, 200); + MLOGD("callTIme:%d, location:%d\n", callTime, enATcmdType); + SLOGD("revBuf******\n %s \n*********************\n\n",ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enATcmdType); + timeout_count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + + } + return SF_SUCCESS; + } +SINT32 eg91_server_acm_open(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + + SINT16 ttyRet = SF_SUCCESS; + SINT16 ret = SF_SUCCESS; + SINT16 sts = 1; + UINT16 timeout_count = 0; + UINT16 callTime = 0; + UINT16 reOpenTimes = 2; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR tempStr[32] = { 0 }; + MODULE_SERVER_ACM_OPEN_E enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QISTATE; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + SLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch(enATcmdType) + { + case MODULE_SERVER_ACM_OPEN_AT_QICSGP: + if(strstr(ttyData, "OK") || strstr(ttyData, "ERROR")) + { + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QIACT; + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", TCP_PDP, pStaticParam->ApnGPRS, pStaticParam->ApnUsername, pStaticParam->ApnPassword); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_ACM_OPEN_AT_QISTATE: + sprintf(ttyData, "AT+QISTATE=0,%d\r", TCP_PDP);/**/ + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QISTATE_CHECK; + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + + case MODULE_SERVER_ACM_OPEN_AT_QISTATE_CHECK:/**/ + if(strstr(ttyData,"+QISTATE:")) + { + + /* + UINT8 qiState[7][20] ={0}; + UINT8 i = 0; + strcpy((char*)qiState[i],strtok(ttyData, ",")); + while(i<6) + { + i++; + strcpy((char*)qiState[i],strtok(NULL, ",")); + MLOGD("qiState=%s\n",qiState[i]); + } + */ + char *p = NULL; + p = strstr(ttyData,"+QISTATE:"); + p = strchr(p, ','); + p = strchr(p+1, ','); + p = strchr(p+1, ','); + p = strchr(p+1, ','); + p = strchr(p+1, ','); + + //if(strncmp((char*)qiState[i], "2", 1) == 0) + if(atoi(p+1) == 2) + { + MLOGD("Keep alive login ACM.\n"); + sprintf(ttyData, "AT+QIRD=%d,228\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(atoi(p+1) == 4) + { + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QIDEACT; + sprintf(ttyData, "AT+QICLOSE=%d,1\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QICSGP; + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + } + else if((strstr(ttyData,"OK")) || (timeout_count > 200)) + { + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QIDEACT; + sprintf(ttyData, "AT+QICLOSE=%d,1\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + case MODULE_SERVER_ACM_OPEN_AT_QISTATE_TEST: + sprintf(ttyData, "AT+QIRD=%d,228\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + + case MODULE_SERVER_ACM_OPEN_AT_QIDEACT:/**/ + if(strstr(ttyData, "OK") || strstr(ttyData, "ERROR")) + { + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QICSGP; + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case MODULE_SERVER_ACM_OPEN_AT_QIACT: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + sprintf(ttyData, "AT+QIACT=%d\r", TCP_PDP);/**/ + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QICFG; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(strstr(ttyData, "ERROR")) + { + sts = 0; + ret = SF_4G_ERROR_AT_READ; + } + break; + + case MODULE_SERVER_ACM_OPEN_AT_QICFG: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + sprintf(ttyData,"%s","AT+QICFG=\"tcp/keepalive\",1,3,25,3\r");/**/ + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_QIOPEN; + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else if(strstr(ttyData, "ERROR")) + { + callTime++; + if(callTime < TCP_PDP_TRY_TIME) + { + sf_sleep_s(2); + sprintf(ttyData, "AT+QIACT=%d\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + callTime=0; + sts = 0; + ret = SF_4G_ERROR_AT_ACTIVE; + MLOGE("Moudle QIACT ERROR.DATA:%s\n", ttyData); + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + else if(timeout_count > 100) + { + sts = 0; + ret = SF_4G_ERROR_AT_ACTIVE; + MLOGE("Moudle QIACT timeout\n"); + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_ACM_OPEN_AT_QIOPEN: + if(strstr(ttyData, "OK")) + { + timeout_count = 0; + callTime = 0; + #if defined(CFG_TRANSDATA_AT) + sprintf(ttyData,"AT+QIOPEN=%d,%d,\"TCP\",\"%s\",%d,0,0\r", TCP_PDP, TCP_PDP, pStaticParam->AcmIP, 6600); + #else + sprintf(ttyData,"AT+QIOPEN=%d,%d,\"TCP\",\"%s\",%d,0,0\r", TCP_PDP, TCP_PDP, pStaticParam->AliveIp, pStaticParam->AlivePort); + #endif + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_ATE0; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if((strstr(ttyData, "ERROR")) || (callTime > 100)) + { + timeout_count = 0; + callTime = 0; + #if defined(CFG_TRANSDATA_AT) + sprintf(ttyData,"AT+QIOPEN=%d,%d,\"TCP\",\"%s\",%d,0,0\r", TCP_PDP, TCP_PDP, pStaticParam->AcmIP, 6600); + #else + sprintf(ttyData,"AT+QIOPEN=%d,%d,\"TCP\",\"%s\",%d,0,0\r", TCP_PDP, TCP_PDP, pStaticParam->AliveIp, pStaticParam->AlivePort); + #endif + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_ATE0; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + callTime++; + } + break; + + case MODULE_SERVER_ACM_OPEN_AT_ATE0: + timeout_count = 0; + SF_CHAR *pbuf = NULL; + pbuf = strstr(ttyData, "+QIOPEN:"); + + if(pbuf != NULL) + { + memcpy(tempStr, pbuf, 12); + } + + if((strncmp(tempStr, "+QIOPEN:", 8) == 0)&&(tempStr[11]=='0')) + { + return SF_SUCCESS; + } + else if(((strncmp(tempStr, "+QIOPEN:", 8) == 0)&&(tempStr[11]!='0')) || (strncmp(tempStr, "+CME ERROR", 10) == 0)) + { + if(reOpenTimes) + { + reOpenTimes--; + MLOGE("QIOPEN Fail, re connect acm.\n"); + #if defined(CFG_TRANSDATA_AT) + sprintf(ttyData,"AT+QIOPEN=%d,%d,\"TCP\",\"%s\",%d,0,0\r", TCP_PDP, TCP_PDP, pStaticParam->AcmIP, 6600); + #else + sprintf(ttyData,"AT+QIOPEN=%d,%d,\"TCP\",\"%s\",%d,0,0\r", TCP_PDP, TCP_PDP, pStaticParam->AliveIp, pStaticParam->AlivePort); + #endif + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + + } + else + { + MLOGE("Re connect acm fail.\n"); + ret = SF_4G_ERROR_AT_OPEN; + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + else + { + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + if(callTime > 600) + { + MLOGE("Connect acm timeout.\n"); + ret = SF_4G_ERROR_AT_TIMEOUT; + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_OPEN_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + callTime++; + break; + + case MODULE_SERVER_ACM_OPEN_AT_END: + if(strstr(ttyData, "OK")) + { + return ret; + } + if(!strstr(ttyData, "+QIRD: 0") && (ret == SF_SUCCESS)) + { + memset(&pfnParam->arrttyData, '\0', SF_TTYUSB_RECV_MAX); + memcpy(&pfnParam->arrttyData, ttyData, SF_TTYUSB_RECV_MAX); + return SF_SUCCESS; + } + else + return ret; + default: + break; + } + + SLOGI("sendBuf******\n %s \n*********************\n\n",ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + + SLOGI("revBuf******\n %s \n*********************\n\n",ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enATcmdType); + timeout_count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + } + return ret; +} + + + SINT32 eg91_server_acm_transfer(SF_DATA_ATTR_S *psenddate, SF_FN_PARAM_S *pfnParam, UINT8 needRepose) + { + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + + SINT32 ttyRet = SF_SUCCESS; + SINT32 ret = SF_SUCCESS; + SINT16 sts = 1; + UINT16 timeout_count = 0; + UINT16 callTime = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + MODULE_SERVER_ACM_WRITE_E enATcmdType = MODULE_SERVER_ACM_WRITE_AT_QISEND; + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + break; + + switch(enATcmdType) + { + case MODULE_SERVER_ACM_WRITE_AT_QISEND: + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_SENDING; + sprintf(ttyData,"AT+QISEND=%d,%d\r", TCP_PDP, psenddate->dataSize-3); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_SERVER_ACM_WRITE_AT_SENDING: + if(strstr(ttyData, ">")) + { + timeout_count = 0; + callTime = 0; + if(needRepose) + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_QIRD; + else + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_END; + + memset(ttyData, '\0', sizeof(ttyData)); + ttyRet = sf_hal_ttyusb2_write((SF_CHAR*)psenddate->databuf, psenddate->dataSize-2); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_ACM_WRITE_AT_QIRD: + if((strstr(ttyData, "recv")) || (strstr(ttyData, "re"))) + { + timeout_count = 0; + sprintf(ttyData, "AT+QIRD=%d,228\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_END; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else if(strstr(ttyData, "closed")) + { + callTime = 0; + MLOGE("send data to acm:connection closed"); + return SF_4G_ERROR_AT_DISCONNECT; + } + else + { + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + callTime++; + timeout_count = 0; + if(callTime > 50) + { + callTime = 0; + sprintf(ttyData, "AT+QIRD=%d,228\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_ATE0; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + } + break; + case MODULE_SERVER_ACM_WRITE_AT_ATE0: + if(!strstr(ttyData, "+QIRD: 0")) + { + memset(&psenddate->databuf, '\0', sizeof(psenddate->databuf)); + memcpy(psenddate->databuf, ttyData, SF_TTYUSB_RECV_MAX); + sts = 0; + return SF_SUCCESS; + } + else + { + + callTime++; + if(callTime < 5) + { + sf_sleep_s(10); + + sprintf(ttyData, "AT+QIRD=%d,228\r", TCP_PDP); + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_ATE0; + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + else + { + callTime = 0; + return SF_4G_ERROR_AT_DISCONNECT; + + enATcmdType = MODULE_SERVER_ACM_WRITE_AT_QIDEACT; + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + break; + case MODULE_SERVER_ACM_WRITE_AT_QIDEACT: + return SF_4G_ERROR_AT_DISCONNECT; + case MODULE_SERVER_ACM_WRITE_AT_END: + memset(&psenddate->databuf, '\0', SF_TTYUSB_RECV_MAX); + memcpy(psenddate->databuf, ttyData, SF_TTYUSB_RECV_MAX); + sts = 0; + return SF_SUCCESS; + default: + break; + } + + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enATcmdType); + timeout_count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + } + return ret; + } + + SINT32 eg91_server_acm_close(SF_FN_PARAM_S *pfnParam) + { + + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + SINT32 ttyRet = SF_SUCCESS; + SINT32 ret = SF_SUCCESS; + SINT16 sts = 1; + UINT16 timeout_count = 0; + UINT16 callTime = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + MODULE_SERVER_ACM_CLOSE_E enATcmdType = MODULE_SERVER_ACM_CLOSE_AT_QICLOSE; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + break; + + switch(enATcmdType) + { + case MODULE_SERVER_ACM_CLOSE_AT_QICLOSE: + enATcmdType = MODULE_SERVER_ACM_CLOSE_AT_QIDEACT; + sprintf(ttyData, "AT+QICLOSE=%d,1\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + break; + + case MODULE_SERVER_ACM_CLOSE_AT_QIDEACT: + if((strstr(ttyData, "OK")) || (strstr(ttyData,"ERROR")) || (callTime>100)) + { + timeout_count = 0; + callTime = 0; + enATcmdType = MODULE_SERVER_ACM_CLOSE_AT_END; + sprintf(ttyData, "AT+QIDEACT=%d\r", TCP_PDP); + ttyRet = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + SF_APPCOMM_CHECK_RETURN(ttyRet, ttyRet); + } + break; + + case MODULE_SERVER_ACM_CLOSE_AT_END: + if((strstr(ttyData, "OK")) || (callTime > 100)) + { + timeout_count = 0; + return SF_SUCCESS; + } + + break; + + default: + break; + } + + SLOGD("sendBuf******\n %s \n*********************\n\n",ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + + SLOGD("revBuf******\n %s \n*********************\n\n",ttyData); + timeout_count++; + if(timeout_count > 200) + { + SLOGE("[ERROR]Init timeout, enATcmdType=%d\n", enATcmdType); + timeout_count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + } + return ret; + } + + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/4gMng/sf_eg91_sim.c b/code/application/source/sf_app/code/source/4gMng/sf_eg91_sim.c new file mode 100755 index 000000000..27e15f5f0 --- /dev/null +++ b/code/application/source/sf_app/code/source/4gMng/sf_eg91_sim.c @@ -0,0 +1,2143 @@ +#include +#include +#include +#include +#include +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#include "sf_log.h" + +#include "sf_hal_ttyusb.h" +#include "sf_systemMng.h" + +#include "sf_opera_adapt.h" +#include "sf_eg91_sim.h" +#include "sf_param_common.h" + +unsigned long int LocateTime = 0; + + +void eg91_mark_time_set(unsigned long int MarkTime) +{ + MLOGD("markTime:%ld\n", MarkTime); + LocateTime = MarkTime; +} + +static void eg91_parse_module_version_detail(SF_CHAR* pTemp, SF_CHAR *pT1, SF_CHAR *pT2, SF_CHAR *pT4, SF_CHAR *version) +{ + SF_PDT_PARAM_STATISTICS_S *sim_info_t = sf_statistics_param_get(); + SF_CHAR str0[5] = { 0 }; + SF_CHAR str1[5] = { 0 }; + SF_CHAR str2[5] = { 0 }; + SF_CHAR str3[5] = { 0 }; + SF_CHAR str4[256] = { 0 }; + SF_CHAR str5[256] = { 0 }; + SF_CHAR* pT5=NULL; + memcpy(str1, pTemp + 4, pT1 - pTemp - 4); + //printf("str1 = %s\n", str1); + memcpy(str2, pT1 + 3, 2); + //printf("str2 = %s\n", str2); + memcpy(str3, pT1 + 6, 2); + //printf("str3 = %s\n", str3); + + if(strstr(sim_info_t->ModuleVersion, EG91)) + { + sprintf(str0, "%s", "91"); + } + else if(strstr(sim_info_t->ModuleVersion, EG95)) + { + sprintf(str0, "%s", "95"); + } + else + { + sprintf(str0, "%s", "UN"); + } + + if(pT2 != NULL) + { + strcpy(str4, pT2 + 1); + //printf("str4 = %s\n", str4); + pT5 = strtok(str4, "\r\n"); + + + if(pT5 != NULL) + { + strcpy(str5, pT5); + //printf("str5 = %s\n",str5); + + if (pT4 != NULL) + sprintf(version, "S%sY%sY%sY%sY%sOS", str0, str1, str2, str3, str5); + else + sprintf(version, "S%sY%sY%sY%sY%sS", str0, str1, str2, str3, str5); + } + else + { + if (pT4 != NULL) + sprintf(version, "S%sY%sY%sY%sOS", str0, str1, str2, str3); + else + sprintf(version, "S%sY%sY%sY%sS", str0, str1, str2, str3); + } + } + else + { + if (pT4 != NULL) + sprintf(version, "S%sY%sY%sY%sOS", str0, str1, str2, str3); + else + sprintf(version, "S%sY%sY%sY%sS", str0, str1, str2, str3); + } + + MLOGD("module_QGver = %s\n", version); + return; +} + +static SINT32 eg91_parse_module_version(SF_CHAR *pTemp, SF_CHAR *version) +{ + SF_COMM_CHECK_POINTER(pTemp,SF_FAILURE); + + SF_CHAR *pT1 = NULL; + SF_CHAR *pT2 = NULL; + SF_CHAR *pT3 = NULL; + SF_CHAR *pT4 = NULL; + + pT1 = strstr(pTemp, "FAR"); + pT2 = strstr(pTemp, "_"); + pT3 = strstr(pTemp, "GAR"); + pT4 = strstr(pTemp, "OCPU"); + + MLOGD("pTemp = %s\n", pTemp); + MLOGD("pT1 = %s\n", pT1); + MLOGD("pT2 = %s\n", pT2); + MLOGD("pT3 = %s\n", pT3); + + if(pT1 != NULL) + eg91_parse_module_version_detail(pTemp, pT1, pT2, pT4, version); + else if(pT3 != NULL) + eg91_parse_module_version_detail(pTemp, pT3, pT2, pT4, version); + + + MLOGD("version:%s\n", version); + return SF_SUCCESS; +} + +static SINT32 eg91_module_Polling_Comparison_CIMI(SF_CHAR *operatorName) +{ + SF_COMM_CHECK_POINTER(operatorName,SF_FAILURE); + UINT8 i = 0; + static UINT8 CIMIcount = 0; + static SF_CHAR strCIMI[5][8] = { 0 }; + + MLOGD("CIMIcount = %d,operatorName = [%s]\n",CIMIcount,operatorName); + if(operatorName == SF_NULL) + return SF_FAILURE; + + if(CIMIcount > 5) + return SF_FAILURE; + + for(i=0;i<5;i++) + { + MLOGD("strCIMI[%d]: [%s]\n",i,strCIMI[i]); + if(strncmp(strCIMI[i], operatorName, 5) == 0) + return SF_FAILURE; + else + { + if(strlen(strCIMI[i]) == 0) + { + memcpy(strCIMI[i], operatorName, 5); + CIMIcount++; + MLOGD("strCIMI[%d]: [%s]\n",i,strCIMI[i]); + return SF_SUCCESS; + } + + + } + + + } + return SF_SUCCESS; +} + +SINT32 eg91_other_sim_apn_cfg(SF_PDT_PARAM_STATISTICS_S *pstaticParam) +{ + FILE *fp = NULL; + SF_CHAR linestr[128] = {0}; + SF_CHAR *pTemp = SF_NULL; + UINT32 enbleValue = 0; + + fp = fopen(SIM_AUTO_MATCH_FILE_PATH, "r"); + if(fp == NULL) + { + SLOGE("open file [%s] failed!\n", SIM_AUTO_MATCH_FILE_PATH); + return SF_FAILURE; + } + + { + fgets(linestr, 128, fp); + if(strstr(linestr, "Value:") == NULL) { + fclose(fp); + return SF_FAILURE; + } + sscanf(linestr, "Value:%d",&enbleValue); + if(enbleValue == 0) { + fclose(fp); + return SF_FAILURE; + } + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + + if(strstr(linestr, "4G APN:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->ApnGPRS); + SLOGD("4G APN:<%s>\n", pstaticParam->ApnGPRS); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "4G UserName:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->ApnUsername); + SLOGD("4G UserName:<%s>\n", pstaticParam->ApnUsername); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "4G Password:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->ApnPassword); + SLOGD("4G Password:<%s>\n", pstaticParam->ApnPassword); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "MMSC:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->MMSC); + SLOGD("MMSC:<%s>\n", pstaticParam->MMSC); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "MMS APN:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->MMSAPN); + SLOGD("MMS APN:<%s>\n", pstaticParam->MMSAPN); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "Proxy:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->Proxy); + SLOGD("Proxy:<%s>\n", pstaticParam->Proxy); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "Port:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->Port); + SLOGD("Port:<%s>\n", pstaticParam->Port); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "UserName:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->UserName); + SLOGD("UserName:<%s>\n", pstaticParam->UserName); + } + + if(feof(fp)) { + fclose(fp); + return SF_SUCCESS; + } + fgets(linestr, 128, fp); + if(strstr(linestr, "Password:<") != NULL) { + sscanf(linestr, "%*[^<]<%[^>]",pstaticParam->Password); + SLOGD("Password:<%s>\n", pstaticParam->Password); + } + + fclose(fp); + } + + return SF_SUCCESS; + +} + +SINT32 eg91_iccid_get(SF_CHAR *iccid,SF_FN_PARAM_S *pfnParam) +{ + + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + SINT16 count = 0; + SF_CHAR GsnNow[22] = { 0 }; + SF_CHAR *pStr = NULL; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + + sprintf(ttyData, "AT+QCCID\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + while(count < 3) + { + sf_hal_ttyusb2_read(ttyData, 150); + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + break; + + if(ttyData[0] != '\0') + { + UINT8 tempICCID[21]={0}; + pStr = strstr(ttyData,"+QCCID: "); + if(pStr != NULL) + { + memcpy(tempICCID, pStr+8, 20); + + if((tempICCID[19] <='9') && (tempICCID[19] >='0')) + { + tempICCID[20] = '\0'; + } + else + { + tempICCID[19] = '\0'; + } + strcpy(GsnNow, (char*)tempICCID); + strcpy(iccid, GsnNow); + MLOGD("ICCID=%s\n",tempICCID); + break; + } + } + + + count++; + } + + return SF_SUCCESS; +} + +SINT32 eg91_qsclk_set(SF_FN_PARAM_S *pfnParam) +{ + + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + SINT32 sts = 1; + SINT32 count = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SIM_SLEEP_NET_E enMmcLocation; + enMmcLocation = SIM_SLEEP_FIRST; + + + + + while(sts) + { + + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + MLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch (enMmcLocation) + { + case SIM_SLEEP_FIRST: + { + SF_PDT_PARAM_CFG_S *pstParam = pfnParam->pstParam; + if(sf_poweron_type_get() != SF_MCU_STARTUP_RESET + && sf_poweron_type_get() != SF_MCU_STARTUP_DP ) + enMmcLocation = SIM_SLEEP_QSCLK; + else + enMmcLocation = SIM_SLEEP_QSCEX; +// sprintf(ttyData, "%s", "AT+QCFG=\"urc/ri/other\",\"pulse\"\r"); + sprintf(ttyData, "%s", "AT+QCFG=\"urc/ri/other\",\"pulse\",120,2\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + case SIM_SLEEP_QSCLK: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_SLEEP_QSCEX; + sprintf(ttyData, "AT+QSCLK=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case SIM_SLEEP_QSCEX: + if(strstr(ttyData, "OK") || strstr(ttyData, "ERROR")) + { + + sts = 0; + return SF_SUCCESS; + } + break; + + case SIM_SLEEP_EXIT: + break; + default: + break; + + + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("count:%d, location:%d\n", count, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + count++; + if(count > 300) + { + MLOGE("timeout, enMmcLocation=%d\n", enMmcLocation); + count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + + } + return SF_SUCCESS; +} + +SINT32 eg91_usb_net_apn_cfg(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam, SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam, SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit, SF_FAILURE); + + UINT16 count = 0; + SINT16 ret = SF_SUCCESS; + SINT16 ret1 = SF_SUCCESS; + SINT32 fd = 0; + int retryTime = 0; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT8 sts = 1; + USBNET_APN_INIT_e enMmcLocation; + enMmcLocation = USBNET_APN_INIT_FIRST; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + + + sprintf(ttyData, "AT\r"); + ret1 = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + if(ret1 == SF_FAILURE) + { + ret1 = SF_4G_ERROR_MODULE_OPEN; + return ret1; + } + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + MLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + SLOGD("time:%d--MMC:%d\n", count, enMmcLocation); + sf_hal_ttyusb2_read(ttyData, 100); + + count++; + if(count > 300) + { + SLOGE("timeout, enMmcLocation=%d\n", enMmcLocation); + count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + + SLOGD("ttyData=%s\n",ttyData); + + switch (enMmcLocation) + { + case USBNET_APN_INIT_FIRST: + SLOGD("ApnGPRS:%s\n", pStaticParam->ApnGPRS); + /*if(strstr(sfPara->ApnGPRS, V_MODULE_APN)) + { + sprintf(ttyData, "AT+QICSGP=%d\r", V_PDP_INDEX); + enMmcLocation = USBNET_APN_QICSGP1; + } + else if(strstr(sfPara->ApnGPRS, A_MODULE_APN)) + { + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", A_PDP_INDEX, + sfPara->ApnGPRS, sfPara->ApnUsername, sfPara->ApnPassword); + enMmcLocation = USBNET_APN_QICSGP2; + } + else*/ + + { + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", E_PDP_INDEX, + pStaticParam->ApnGPRS, pStaticParam->ApnUsername, pStaticParam->ApnPassword); + enMmcLocation = USBNET_APN_QICSGP2; + } + + ret1 = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + if(ret1 == SF_FAILURE) + { + ret1 = SF_4G_ERROR_MODULE_OPEN; + return ret1; + /* + LOG_DM_RS("4G USB has disconnet.\n"); + sf_ttyusb_deinit(); + fd = sf_ttyfd_init_tryother(); + if(fd < 0) + { + ret1 = SF_GPRS_MODULE_ERROR_OPEN; + return ret1; + } + ret1 = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + */ + } + + break; + case USBNET_APN_QICSGP1: + if(strstr(ttyData, "OK")) + { + if(strstr(ttyData, "+QICSGP: 0") || strstr(ttyData, "+QICSGP: 1,\"\"")) + { + + + count = 0; + sprintf(ttyData, "AT+QICSGP=%d,1,\"%s\",\"%s\",\"%s\",1\r", V_PDP_INDEX, + pStaticParam->ApnGPRS, pStaticParam->ApnUsername, pStaticParam->ApnPassword); + enMmcLocation = USBNET_APN_QICSGP2; + } + else + { + sprintf(ttyData, "AT\r"); + } + ret1 = sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + if(ret1 == SF_FAILURE) + { + ret1 = SF_4G_ERROR_MODULE_OPEN; + return ret1; + } + } + break; + case USBNET_APN_QICSGP2: + if(strstr(ttyData, "OK")) + { + count = 0; + sts = 0; + ret = SF_SUCCESS; + } + break; + + } + + + } + + return ret; + +} + +SINT32 eg91_sim_init(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + UINT16 index = 0; + UINT16 count = 0; + UINT16 callTime = 0; + SINT16 ret = SF_SUCCESS; + + SF_CHAR GsnSaved[22] = { 0 }; + SF_CHAR GsnNow[22] = { 0 }; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + SF_CHAR operationCode[6] = { 0 }; + UINT8 sts = 1; + UINT8 ModuelV05 = 0; /* Record the mode version is 05 or 07*/ + SF_CHAR *pTemp = NULL; + + SF_CHAR *p = NULL; + SF_CHAR tempICCID[21] = { 0 }; + SF_CHAR lastICCID[21] = { 0 }; + SF_CHAR *pStr = NULL; + + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + SIM_INIT_E enMmcLocation; + enMmcLocation = SIM_INIT_ATE; + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + MLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch(enMmcLocation) + { + case SIM_INIT_ATE: + enMmcLocation = SIM_INIT_GSN;//SIM_INIT_DEBUG; + sprintf(ttyData, "ATE1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_INIT_DEBUG: + enMmcLocation = SIM_INIT_GSN; + sprintf(ttyData, "%s", "AT+QGPSCFG=\"outport\",\"uartdebug\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_INIT_FIRST: + if(strstr(ttyData, "+QSIMSTAT: 0,0")) + { + callTime++; + if(callTime > 50) + { + SLOGE("SimCard not inserted.\n"); + memset(&pStaticParam->SimID,'\0',SF_ICCID_MAX_LEN); + return SF_4G_ERROR_NO_SIMCARD; + } + else + { + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + } + else if(strstr(ttyData, "+QSIMSTAT: 0,1")) + { + count = 0; + callTime = 0; +// enMmcLocation = SIM_INIT_QNTP; +// sprintf(ttyData, "%s", "AT+QCFG=\"ntp\",3,5\r"); + enMmcLocation = SIM_INIT_QURCCFG; + sprintf(ttyData, "%s", "AT+QURCCFG=\"urcport\",\"usbat\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(ttyData, "+CPIN: NOT INSERTED")) + { + MLOGE("SimCard not inserted.\n"); + memset(&pStaticParam->SimID,'\0',SF_ICCID_MAX_LEN); + return SF_4G_ERROR_NO_SIMCARD; + } + else + { + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_QNTP: + //if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QURCCFG; + sprintf(ttyData, "%s", "AT+QURCCFG=\"urcport\",\"usbat\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + + } + break; + + case SIM_INIT_QURCCFG: + { + enMmcLocation = SIM_INIT_QCFG; + sprintf(ttyData, "%s", "AT+QCFG=\"risignaltype\",\"physical\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_QCFG: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QLWCFG; + sprintf(ttyData, "%s", "AT+QCFG=\"urc/ri/other\",\"off\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_INIT_QCFG_PLUSE: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QLWCFG; + sprintf(ttyData, "%s", "AT+QCFG=\"urc/ri/other\",\"pulse\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_INIT_QNVW: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QLWCFG; + sprintf(ttyData, "%s", "AT+QNVW=3006,0,\"FF00\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_INIT_QLWCFG: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QLWCFG_1; + sprintf(ttyData, "%s", "AT+QLWCFG=\"urc\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case SIM_INIT_QLWCFG_1: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_CGDCONT; + sprintf(ttyData, "%s", "AT+QLWCFG=\"startup\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_ICCID: + if(strstr(ttyData, "READY")) + { + enMmcLocation = SIM_INIT_ICCID_1; + sprintf(ttyData, "%s", "AT+QCCID\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case SIM_INIT_GSN: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_ATI; + sprintf(ttyData, "%s", "AT+GSN\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case SIM_INIT_ATI: + if(ttyData[0] != '\0') + { + for(index = 0; index < SF_TTYUSB_RECV_MAX; index++) + { + if((ttyData[index] == '8')&&(ttyData[index+1] == '6')) + { + SF_CHAR tempImei[16] = {0}; + UINT8 p = 0; + for(p=0; p < IMEI_LEN; p++) + { + if((ttyData[p+index] >= '0')&&(ttyData[p+index] <= '9')) + tempImei[p] = ttyData[p+index]; + else + tempImei[p] = '\0'; + } + tempImei[15] = '\0'; + strcpy(GsnNow, tempImei); + break; + } + } + } + + if((GsnNow[0] != '\0') && (strncmp(GsnNow, GsnSaved, IMEI_LEN) == 0)) + { + if(strcasecmp(GsnNow, pStaticParam->IMEI) != 0)/* Added by MaxLi 2022/03/02--20:40:51*/ + { + MLOGD("%s\n", GsnNow); + + sprintf(pStaticParam->IMEI, "%s", GsnNow); + //LOGI_R("%s", sim_info_t2->IMEI); + MLOGD("imei:%s\n", pStaticParam->IMEI); + + } + strcpy(ttyData, "ATI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + enMmcLocation = SIM_INIT_QFLIST; + } + else + { + strcpy(GsnSaved, GsnNow); + GsnNow[0] = '\0'; + + sprintf(ttyData, "%s", "AT+GSN\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(100); + } + break; + + case SIM_INIT_QFLIST: + if((strstr(ttyData, "OK") != NULL) || (strstr(ttyData, "ERROR") != NULL)) + { + pTemp = strstr(ttyData, "Revision:"); + if(pTemp != NULL) + { + SF_CHAR modulVerStr[256] = { 0 }; + strcpy(modulVerStr, pTemp+10); + pTemp = strtok(modulVerStr, "OK"); + p = strtok(pTemp, "\r\n"); + if(strcasecmp(p, pStaticParam->ModuleVersion) != 0)/* Added by MaxLi 2022/03/02--20:41:28*/ + { + strcpy(pStaticParam->ModuleVersion, p); + } + } + + if((strstr(ttyData, "AFAR05"))) + { + enMmcLocation = SIM_INIT_QFLIST_1; + ModuelV05 = 1; + strcpy(ttyData, "at+qflst=\"../../usr/fota_ip_a/update_report.ur\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + callTime = 0; + sf_sleep_ms(500); + } + else if(strstr(ttyData, "AFAR07")) + { + enMmcLocation = SIM_INIT_QFLIST_1; + strcpy(ttyData, "at+qflst=\"../../data/fota_ip_a/update_report.ur\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + callTime = 0; + sf_sleep_ms(500); + } + else + { + enMmcLocation = SIM_INIT_QGMR; + callTime = 0; + sprintf(ttyData, "%s", "AT+QGMR\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(100); + } + } + else + { + strcpy(ttyData, "ATI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(100); + } + break; + + case SIM_INIT_QFLIST_1: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QGMR; + callTime = 0; + sprintf(ttyData, "%s", "AT+QGMR\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(100); + } + else if(strstr(ttyData, "ERROR: 417")) + { + enMmcLocation = SIM_INIT_QFLIST_2; + + if(ModuelV05 == 1) + { + strcpy(ttyData, "at+qfopen=\"../../usr/fota_ip_a/update_report.ur\",1\r"); + } + else + { + strcpy(ttyData, "at+qfopen=\"../../data/fota_ip_a/update_report.ur\",1\r"); + } + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(1000); + } + else + { + callTime++; + if(callTime > 10) + { + callTime = 0; + enMmcLocation = SIM_INIT_QFLIST; + strcpy(ttyData, "ATI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(100); + } + sf_sleep_ms(500); + } + break; + + case SIM_INIT_QFLIST_2: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_QGMR; + callTime = 0; + sprintf(ttyData, "%s", "AT+QGMR\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(100); + } + else + { + enMmcLocation = SIM_INIT_QFLIST; + sprintf(ttyData, "ATI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(100); + } + break; + case SIM_INIT_QGMR: + if(strstr(ttyData, GPRS_MODULE_TYPE_EG91) != NULL) + { + char subTemp[SF_MODULE_VER_MAX_LEN]={0}; + eg91_parse_module_version(strstr(ttyData, GPRS_MODULE_TYPE_EG91), subTemp); + + if(strcasecmp(subTemp, pStaticParam->ModuleSubversion) != 0)/* Added by MaxLi 2022/03/02--20:41:52*/ + { + strcpy(pStaticParam->ModuleSubversion, subTemp); + } + + if(strstr(pStaticParam->ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) + { + enMmcLocation = SIM_INIT_QNVFR; + sprintf(ttyData, "%s","at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_INIT_FIRST; + callTime = 0; + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + } + else if(strstr(ttyData, GPRS_MODULE_TYPE_EG95) != NULL) + { + char subTemp[SF_MODULE_VER_MAX_LEN]={0}; + eg91_parse_module_version(strstr(ttyData, GPRS_MODULE_TYPE_EG95), subTemp); + + if(strcasecmp(subTemp, pStaticParam->ModuleSubversion) != 0)/* Added by MaxLi 2022/03/02--20:42:15*/ + { + strcpy(pStaticParam->ModuleSubversion, subTemp); + } + + if(strstr(pStaticParam->ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) + { + enMmcLocation = SIM_INIT_QNVFR; + sprintf(ttyData, "%s","at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else + { + enMmcLocation = SIM_INIT_FIRST; + callTime = 0; + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + } + else + { + callTime++; + if(callTime > 5) + { + callTime = 0; + if(strstr(pStaticParam->ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) + { + enMmcLocation = SIM_INIT_QNVFR; + sprintf(ttyData, "%s","at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(pStaticParam->ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) + { + enMmcLocation = SIM_INIT_QNVFR; + sprintf(ttyData, "%s","at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_INIT_FIRST; + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + } + } + break; + + case SIM_INIT_ICCID_1: + if((strstr(ttyData,"+QCCID: ") != NULL)) + { + + pStr = strstr(ttyData,"+QCCID: "); + + memcpy(tempICCID, pStr+8, 20); + + if((tempICCID[19] <= '9') && (tempICCID[19] >= '0')) + tempICCID[20] = '\0'; + else + tempICCID[19] = '\0'; + + if(strncmp(lastICCID, tempICCID, 21) == 0) + { + sprintf(pStaticParam->SimID, "%s", tempICCID); + MLOGD("ICCID=%s\n", pStaticParam->SimID); + callTime=0; + #if defined(CFG_SUPPORT_GPS) + enMmcLocation = SIM_INIT_QGPSXTRA; + sprintf(ttyData,"%s","AT+QGPSXTRA?\r"); + #else + enMmcLocation = SIM_INIT_CIMI; + sprintf(ttyData, "AT+CIMI\r"); + #endif + //enMmcLocation = SIM_INIT_END; + //sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + } + else + { + strcpy(lastICCID, tempICCID); + memset(tempICCID, '\0', sizeof(tempICCID)); + enMmcLocation = SIM_INIT_ICCID_1; + sprintf(ttyData, "AT+QCCID\r"); + } + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + + } + else + { + if(callTime > 10) + { + callTime = 0; + sprintf(ttyData,"%s","AT+QCCID\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + callTime++; + } + break; + case SIM_INIT_QGPSXTRA: + if(strstr(ttyData, "QGPSXTRA: 0")) + { + enMmcLocation = SIM_INIT_CIMI; + sprintf(ttyData,"%s","AT+QGPSXTRA=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + callTime = 0; + } + else if(strstr(ttyData, "QGPSXTRA: 1")) + { + //enMmcLocation = SIM_INIT_END; + //sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + enMmcLocation = SIM_INIT_CIMI; + sprintf(ttyData, "AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_RESET_MODULE: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_GSN; + sf_hal_ttyusb2_deinit(); + sf_hal_ttyusb2_init(); + sprintf(ttyData, "ATE1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case SIM_INIT_CIMI: + pTemp = NULL; + pTemp = strstr(ttyData, "AT+CIMI"); + if(pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + MLOGD("operationCode:%s\n", operationCode); + sprintf(pStaticParam->OperatorCode, "%s", operationCode); + sf_auto_operation_adaptation(pStaticParam->OperatorCode, pStaticParam); + MLOGD("ApnGPRS:%s\n", pStaticParam->ApnGPRS); + if((strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) \ + || (strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN)))//20408 sifar kpn sim + { + pStaticParam->SimType = SF_SIM_MEGA; + //1. mega sim,set pdp 1 apn + ret = eg91_module_Polling_Comparison_CIMI(operationCode);//mega sim,recorde sim operation code + + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", pStaticParam->ApnGPRS); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else if(strstr(pStaticParam->ApnGPRS, APNGPRSTEMP)) + { + #if defined(CFG_SUPPORT_OTHER_SIM) + MLOGD("CFG_SUPPORT_OTHER_SIM-ApnGPRS:%s\n", pStaticParam->ApnGPRS); + #endif + pStaticParam->SimType = SF_SIM_MEGA_IOT; + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else + { + #if defined(CFG_SUPPORT_OTHER_SIM) + eg91_other_sim_apn_cfg(pStaticParam); + + pStaticParam->SimType = SF_SIM_OTHER; + + //2.other sim: version sim + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + { + enMmcLocation = SIM_INIT_CGDCONT_1; + sprintf(ttyData,"%s","AT+QICSGP=1\r"); + } + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + { + enMmcLocation = SIM_INIT_CGDCONT_2; + sprintf(ttyData,"%s","AT+QICSGP=1\r"); + } + else + { + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + } + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + #else + sts = 0; + return SF_4G_ERROR_NO_SUPPOET; + #endif + } + + } + else + { + sprintf(ttyData, "AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(500); + } + break; + + case SIM_INIT_CGDCONT: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_ICCID; + sprintf(ttyData,"%s","AT+CPIN?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_CGDCONT_1: + pTemp = NULL; + pTemp = strstr(ttyData, "+QICSGP:"); + if(pTemp != NULL) + { + pTemp = strtok(ttyData, ","); + MLOGD("pStr:%s\n", pTemp); + + pTemp = strtok(NULL, ","); + MLOGD("pStr:%s\n", pTemp); + + if(strncmp(pTemp, "\"ims\"", 5) == 0) + { + if((strstr(pStaticParam->ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) || (strstr(pStaticParam->ModuleVersion, GPRS_MODULE_TYPE_EG95_V))) + { + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"%s","AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_INIT_QNVFR; + sprintf(ttyData, "%s","at+qnvfr=\"/nv/item_files/modem/uim/gstk/feature_bmsk\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + else + { + enMmcLocation = SIM_INIT_RESET_MODULE; + sprintf(ttyData,"%s","AT+QPRTPARA=3\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + break; + case SIM_INIT_QNVFR: + if(strstr(ttyData, "+QNVFR: 11000000")) + { + enMmcLocation = SIM_INIT_QNVFW; + sprintf(ttyData, "%s", "at+qnvfw=\"/nv/item_files/modem/uim/gstk/feature_bmsk\",01000000\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"%s","AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_QNVFW: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"%s","AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_INIT_CGDCONT_2: + pTemp = NULL; + pTemp = strstr(ttyData, "+QICSGP:"); + if(pTemp != NULL) + { + pTemp = strtok(ttyData, ","); + printf("pStr:%s\n", pTemp); + + pTemp = strtok(NULL, ","); + printf("pStr:%s\n", pTemp); + + if(strncmp(pTemp, "\"nxtgenphone\"", 18) == 0) + { + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"%s","AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_INIT_CGDCONT_3; + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"nxtgenphone\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + break; + + case SIM_INIT_CGDCONT_3: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_CFUN; + sprintf(ttyData,"%s","AT+CFUN=4\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_CFUN: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_CFUN_1; + sprintf(ttyData,"%s","AT+CFUN=1\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_CFUN_1: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_INIT_END; + sprintf(ttyData,"%s","AT\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_INIT_END: + if(strstr(ttyData, "OK")) + { + callTime=0; + sts = 0; + return SF_SUCCESS; + } + else if(strstr(ttyData, "SIM")) + { + + } + else if(strstr(ttyData, "NOT")) + { + return SF_4G_ERROR_NO_SIMCARD; + } + else + { + if((count % 10) == 0) + { + MLOGD("--------count:%d.--------\n",count); + sprintf(ttyData, "AT+CPIN?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + } + break; + + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 300); + SLOGD("callTIme:%d, location:%d\n", callTime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + count++; + if(count > 300) + { + MLOGE("[ERROR]Init timeout, enMmcLocation=%d\n", enMmcLocation); + count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + } + + return ret; +} +SINT32 eg91_register_net_auto(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + UINT16 count = 0; + UINT16 callTime = 0; + SINT16 ret = SF_SUCCESS; + SINT32 csq = 0; + SF_CHAR *pStr = NULL; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT8 sts = 1; + unsigned long int locateTime = 0; + SF_CHAR operationCode[6] = { 0 }; + SF_CHAR *pTemp = NULL; + SIM_REG_NET_e enMmcLocation; + enMmcLocation = SIM_REG_NET_FIRST; + //static SF_CHAR cimitestflagpir = 0; + #if SF_QLOG_ENABLE + SF_PDT_PARAM_CFG_S *pstparam = pfnParam->pstParam; + #endif + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + MLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + + + switch (enMmcLocation) + { + case SIM_REG_NET_FIRST: + enMmcLocation = SIM_REG_NET_FIRST_1; + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + break; + + case SIM_REG_NET_FIRST_1: + if(strstr(ttyData, "+QSIMSTAT: 0,0")) + { + callTime++; + if(callTime > 50) + { + MLOGE("SimCard not inserted.\n"); + return SF_4G_ERROR_NO_SIMCARD; + + } + else + { + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + } + else if(strstr(ttyData, "+QSIMSTAT: 0,1")) + { + +#if SF_QLOG_ENABLE + + if(pstparam->DebugMode) + { + enMmcLocation = SIM_REG_NET_FIRST_1_1; + sprintf(ttyData, "at+qcfg=\"dbgctl\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + count = 0; + callTime = 0; + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + { + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + { + enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"nxtgenphone\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_REG_NET_FIRST_2; + if(strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN) || strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) + sprintf(ttyData,"AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", pStaticParam->ApnGPRS); + else + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + +#else + count = 0; + callTime = 0; + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + { + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + { + enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"nxtgenphone\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_REG_NET_FIRST_2; + if(strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN) || strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) + sprintf(ttyData,"AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r", pStaticParam->ApnGPRS); + else + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } +#endif + + + } + else if(strstr(ttyData, "+CPIN: NOT INSERTED")) + { + MLOGE("SimCard not inserted.\n"); + return SF_4G_ERROR_NO_SIMCARD; + } + else + { + sprintf(ttyData, "AT+QSIMSTAT?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_REG_NET_FIRST_3: + enMmcLocation = SIM_REG_NET_CIMI; + sprintf(ttyData,"%s","AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_REG_NET_CIMI: + pTemp = NULL; + pTemp = strstr(ttyData, "AT+CIMI"); + if(pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + +// if(cimitestflagpir != 0) + { + ret = eg91_module_Polling_Comparison_CIMI(operationCode); + if(ret != SF_SUCCESS) + return SF_4G_ERROR_REG_NET; +// memcpy(operationCode, strcode, 5); + } + + MLOGD("operationCode:%s\n", operationCode); + sprintf(pStaticParam->OperatorCode, "%s", operationCode); + + sf_auto_operation_adaptation(pStaticParam->OperatorCode, pStaticParam); + if((strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) \ + || (strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN))) + { + //other sim card module E +// enMmcLocation = SIM_REG_NET_FIRST_2; +// sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + return SF_4G_ERROR_REG_NET; + } + + } + else + { + sprintf(ttyData, "AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(500); + } + break; + + case SIM_REG_NET_FIRST_1_1: + if(strstr(ttyData, "OK") || strstr(ttyData, "ERROR")) + { + enMmcLocation = SIM_REG_NET_FIRST_1_2; + sprintf(ttyData, "AT+QLWCFG=\"urc\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_REG_NET_FIRST_1_2: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_REG_NET_FIRST_1_3; + sprintf(ttyData, "AT+QLWCFG=\"startup\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_REG_NET_FIRST_1_3: + if(strstr(ttyData, "OK")) + { + count = 0; + callTime = 0; + if(strstr(pStaticParam->ApnGPRS, V_MODULE_APN)) + { + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else if(strstr(pStaticParam->ApnGPRS, A_MODULE_APN)) + { + enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"nxtgenphone\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + + + case SIM_REG_NET_FIRST_2: + if(strstr(ttyData, "OK")) + { + callTime = 0; + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + +#if 1 + case SIM_REG_NET_WSIZE1: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_REG_NET_WSIZE2; + sprintf(ttyData, "AT+QCFG=\"tcp/windowsize\",0,100\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; +#endif + + case SIM_REG_NET_WSIZE2: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_REG_NET_QNWINFO; + sprintf(ttyData, "AT+QNWINFO\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_REG_NET_CGREG: + if(strstr(ttyData, "+CGREG: 0,")) + { + if(strstr(ttyData, "+CGREG: 0,1") || strstr(ttyData, "+CGREG: 0,5")) + { + #if !defined(CFG_SUPPORT_OTHER_SIM) + if(pStaticParam->SimType == SF_SIM_OTHER) + { + sts = 0; + return SF_4G_ERROR_NO_SUPPOET; + } + #endif + + MLOGD("reg net sucess:%s", ttyData); + locateTime = sf_sys_os_time_get(); + eg91_mark_time_set(locateTime); + //cimitestflagpir = 1; + enMmcLocation = SIM_REG_NET_WSIZE1; + sprintf(ttyData, "AT+QCFG=\"tcp/windowsize\",1,100\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + count = 0; + callTime++; + sf_sleep_ms(400); + MLOGD("callTime = %d\n",callTime); + if(callTime > 320) + { + enMmcLocation = SIM_REG_NET_CIMI; + sprintf(ttyData,"%s","AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + callTime = 0; + } + else if(callTime > 180) + { + if((!strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) && (!strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN))) + { + ret = SF_4G_ERROR_REG_NET; + MLOGE("Other sim reg net timeout!"); + return ret; + } + } + else + { + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + + } + } + break; + case SIM_REG_NET_QNWINFO: + if(strstr(ttyData, "+QNWINFO:") != NULL) + { + SLOGI("%s", ttyData); + if(strstr(ttyData, "No Service")) + { + pStaticParam->netGeneration = 2; + } + else if (NULL != strtok(ttyData,"\"")) + { + SF_CHAR netStr[20] = { 0 }; + strcpy(netStr, strtok(NULL,"\"")); + MLOGD("netStr:%s\n", netStr); + if((strstr(netStr,"DD") != NULL)) + { + pStaticParam->netGeneration = 4; + } + else if(strstr(netStr, "CDMA") != NULL || strstr(netStr, "HDR") != NULL \ + || strstr(netStr, "HSUPA") != NULL || strstr(netStr, "HSDPA") != NULL \ + || strstr(netStr, "HSPA+") != NULL) + { + pStaticParam->netGeneration = 3; + } + else + { + pStaticParam->netGeneration = 2; + } + } + + if(pStaticParam->netGeneration == 4)//NetGeneration == 4 + { + enMmcLocation = SIM_REG_NET_QCSQ; + sprintf(ttyData, "AT+QCSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + enMmcLocation = SIM_REG_NET_CSQ; + sprintf(ttyData, "AT+CSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + callTime = 0; + } + } + break; + + case SIM_REG_NET_QCSQ: + if(strstr(ttyData, "+QCSQ:")) + { + SLOGI("%s", ttyData); + pStr = NULL; + pStr = strtok(ttyData, ","); + MLOGI("pStr:%s\n", pStr); + pStr = strtok(NULL, ","); + MLOGI("pStr:%s\n", pStr); + if(pStr != NULL) + { + pStr = strtok(NULL, ","); + MLOGI("pStr:%s\n", pStr); + csq = 0 - atoi(pStr); + MLOGD("csq:%d\n", csq); + pStaticParam->SimSignal = (UINT8)csq; + if(pStaticParam->SimSignal == 0) + { + pStaticParam->SimSignal = 105; + } + + } + else + { + pStaticParam->SimSignal = 0; + ret = SF_4G_ERROR_NO_SIGNAL; + } + MLOGD("apn:%s\n", pStaticParam->ApnGPRS); + return SF_SUCCESS; + } + break; + + case SIM_REG_NET_CSQ: + if(strstr(ttyData, "+CSQ:")) + { + SLOGI("%s", ttyData); + SF_CHAR *pTemp = NULL; + pStr = strstr(ttyData, "+CSQ:") + 6; + printf("pStr:%s\n", pStr); + pTemp = strtok(pStr, ","); + printf("pTemp:%s\n", pTemp); + if(pTemp != NULL) + { + csq = atoi(pTemp); + if((csq > 31) || (csq == 0)) + { + callTime++; + if(callTime <= 10) + { + sprintf(ttyData, "AT+CSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(300); + } + else + { + callTime = 0; + pStaticParam->SimSignal = 0; + return SF_4G_ERROR_NO_SIGNAL; + } + } + else + { + pStaticParam->SimSignal = csq; + ret = SF_SUCCESS; + MLOGD("apn:%s\n", pStaticParam->ApnGPRS); + return SF_SUCCESS; + } + } + else + { + sprintf(ttyData, "AT+CSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + + } + break; + case SIM_REG_NET_COPS: + break; + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + MLOGD("callTIme:%d, location:%d\n", callTime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + count++; + if(count > 300) + { + MLOGE("timeout, enMmcLocation=%d\n", enMmcLocation); + count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + + } + + return ret; +} +SINT32 eg91_register_net_manual(SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pfn_AT_instruction_exit,SF_FAILURE); + UINT16 count = 0; + UINT16 callTime = 0; + SINT16 ret = SF_SUCCESS; + SINT32 csq = 0; + SF_CHAR *pStr = NULL; + SF_CHAR ttyData[SF_TTYUSB_RECV_MAX] = { 0 }; + UINT8 sts = 1; + SF_CHAR operationCode[6] = { 0 }; + SF_CHAR *pTemp = NULL; + SIM_REG_NET_e enMmcLocation; + enMmcLocation = SIM_REG_NET_FIRST; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + + while(sts) + { + if(SF_TRUE == pfnParam->pfn_AT_instruction_exit(0)) + { + MLOGE("4G module has already connected!!!\n"); + return SF_FAILURE; + } + + switch (enMmcLocation) + { + case SIM_REG_NET_FIRST: + //enMmcLocation = SIM_REG_NET_CIMI; + //sprintf(ttyData,"%s","AT+CIMI\r"); + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + break; + case SIM_REG_NET_CIMI: + pTemp = NULL; + pTemp = strstr(ttyData, "AT+CIMI"); + if(pTemp) + { + memcpy(operationCode, pTemp + 10, 5); + MLOGD("operationCode:%s\n", operationCode); + + ret = eg91_module_Polling_Comparison_CIMI(operationCode); + if(ret != SF_SUCCESS) + return SF_4G_ERROR_NO_SUPPOET; + + MLOGD("operationCode:%s\n", operationCode); + sprintf(pStaticParam->OperatorCode, "%s", operationCode); + + sf_auto_operation_adaptation(pStaticParam->OperatorCode, pStaticParam); + if((strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) \ + || (strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN)) )//mega sim,use in abord + { + + enMmcLocation = SIM_REG_NET_FIRST_2; + sprintf(ttyData,"AT+CGDCONT=1,\"IPV4V6\",\"%s\"\r",pStaticParam->ApnGPRS); + //enMmcLocation = SIM_REG_NET_CGREG; + //sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + return SF_4G_ERROR_NO_SUPPOET; + } + + } + else + { + sprintf(ttyData, "AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + sf_sleep_ms(500); + } + break; + + case SIM_REG_NET_WSIZE1: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_REG_NET_WSIZE2; + sprintf(ttyData, "AT+QCFG=\"tcp/windowsize\",1,100\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_REG_NET_WSIZE2: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_REG_NET_QNWINFO; + sprintf(ttyData, "AT+QNWINFO\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + + case SIM_REG_NET_WSIZE3: + if(strstr(ttyData, "OK")) + { + enMmcLocation = SIM_REG_NET_WSIZE1; + sprintf(ttyData, "AT+QCFG=\"tcp/windowsize\",0,100\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + case SIM_REG_NET_CGREG: + if(strstr(ttyData, "+CGREG: 0,")) + { + if(strstr(ttyData, "+CGREG: 0,1") || strstr(ttyData, "+CGREG: 0,5")) + { + MLOGD("reg net sucess:%s", ttyData); + + enMmcLocation = SIM_REG_NET_WSIZE3; + sprintf(ttyData, "AT+QCFG=\"pdp/duplicatechk\",0\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + count = 0; + callTime++; + sf_sleep_ms(400); + MLOGD("callTime = %d\n",callTime); + if(callTime > 320) + { + enMmcLocation = SIM_REG_NET_CIMI; + sprintf(ttyData,"%s","AT+CIMI\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + count = 0; + callTime = 0; + } + else if(callTime > 180) + { + if((!strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN2)) && (!strstr(pStaticParam->ApnGPRS, APNGPRS_WUYUAN))) + { + ret = SF_4G_ERROR_REG_NET; + MLOGE("Other sim reg net timeout!"); + return ret; + } + } + else + { + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + } + } + break; + + case SIM_REG_NET_QNWINFO: + if(strstr(ttyData, "+QNWINFO:") != NULL) + { + SLOGI("%s", ttyData); + if(strstr(ttyData, "No Service")) + { + pStaticParam->netGeneration = 2; + } + else if (NULL != strtok(ttyData,"\"")) + { + SF_CHAR netStr[20] = { 0 }; + strcpy(netStr, strtok(NULL,"\"")); + MLOGD("netStr:%s\n", netStr); + if((strstr(netStr,"DD") != NULL)) + { + pStaticParam->netGeneration = 4; + } + else if(strstr(netStr, "CDMA") != NULL || strstr(netStr, "HDR") != NULL \ + || strstr(netStr, "HSUPA") != NULL || strstr(netStr, "HSDPA") != NULL \ + || strstr(netStr, "HSPA+") != NULL) + { + pStaticParam->netGeneration = 3; + } + else + { + pStaticParam->netGeneration = 2; + } + } + + enMmcLocation = SIM_REG_NET_COPS; + sprintf(ttyData, "AT+COPS?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + break; + + case SIM_REG_NET_COPS: + if(strstr(ttyData, "+COPS:") != NULL) + { + SLOGI("%s", ttyData); + pStr = NULL; + strtok(ttyData, "\""); + pStr = strtok(NULL, "\""); + if(pStr != NULL) + { + strcpy(pStaticParam->ServiceProvider, pStr); + printf("cops1 is %s\r\n", pStr); + printf("cops2 is %s\r\n", pStaticParam->ServiceProvider); + } + + if(pStaticParam->netGeneration == 4)//NetGeneration == 4 + { + enMmcLocation = SIM_REG_NET_QCSQ; + sprintf(ttyData, "AT+QCSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + } + else + { + enMmcLocation = SIM_REG_NET_CSQ; + sprintf(ttyData, "AT+CSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + break; + case SIM_REG_NET_QCSQ: + if(strstr(ttyData, "+QCSQ:")) + { + MLOGI("%s", ttyData); + pStr = NULL; + pStr = strtok(ttyData, ","); + printf("pStr:%s\n", pStr); + pStr = strtok(NULL, ","); + printf("pStr:%s\n", pStr); + if(pStr != NULL) + { + pStr = strtok(NULL, ","); + printf("pStr:%s\n", pStr); + csq = 0 - atoi(pStr); + MLOGD("SINT32:%d\n", csq); + pStaticParam->SimSignal = (UINT8)csq; + //ret = sf_auto_operation_adaptation(sim_info_t->OperatorCode, sim_info_t); + + if(pStaticParam->SimSignal == 0) + { + callTime++; + + if(callTime < 10) + { + sprintf(ttyData, "AT+QCSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + else + { + pStaticParam->SimSignal = 105; + } + } + else + { + ret = SF_SUCCESS; + enMmcLocation = SIM_REG_NET_SAVE; + sprintf(ttyData, "AT&W\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + } + else + { + pStaticParam->SimSignal = 0; + ret = SF_4G_ERROR_NO_SIGNAL; + enMmcLocation = SIM_REG_NET_SAVE; + sprintf(ttyData, "AT&W\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + //MLOGD("apn:%s\n", sim_info_t->ApnGPRS); + } + break; + + case SIM_REG_NET_CSQ: + if(strstr(ttyData, "+CSQ:")) + { + SLOGI("%s", ttyData); + SF_CHAR *pTemp = NULL; + pStr = strstr(ttyData, "+CSQ:") + 6; + printf("pStr:%s\n", pStr); + pTemp = strtok(pStr, ","); + printf("pTemp:%s\n", pTemp); + if(pTemp != NULL) + { + csq = atoi(pTemp); + if((csq > 31) || (csq == 0)) + { + callTime++; + if(callTime <= 10) + { + sprintf(ttyData, "AT+CSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + sf_sleep_ms(300); + } + else + { + callTime = 0; + pStaticParam->SimSignal = 0; + ret = SF_4G_ERROR_NO_SIGNAL; + } + } + else + { + pStaticParam->SimSignal = csq; + //ret = sf_auto_operation_adaptation(sim_info_t->OperatorCode, sim_info_t); + ret = SF_SUCCESS; + MLOGD("apn:%s\n", pStaticParam->ApnGPRS); + + enMmcLocation = SIM_REG_NET_SAVE; + sprintf(ttyData, "AT&W\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + + } + } + else + { + sprintf(ttyData, "AT+CSQ\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + + } + break; + case SIM_REG_NET_SAVE: + if(strstr(ttyData, "OK")) + { + sts = 0; + return SF_SUCCESS; + } + + break; + case SIM_REG_NET_FIRST_1: + enMmcLocation = SIM_REG_NET_FIRST; + sprintf(ttyData,"%s","AT+CGDCONT=1,\"IPV4V6\",\"\"\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + break; + case SIM_REG_NET_FIRST_2: + if(strstr(ttyData, "OK")) + { + callTime = 0; + enMmcLocation = SIM_REG_NET_CGREG; + sprintf(ttyData, "AT+CGREG?\r"); + sf_hal_ttyusb2_write(ttyData, strlen(ttyData)); + + } + break; + default: + break; + } + SLOGD("sendBuf******\n %s \n*********************\n\n", ttyData); + memset(ttyData,'\0',SF_TTYUSB_RECV_MAX); + sf_hal_ttyusb2_read(ttyData, 200); + SLOGD("callTIme:%d, location:%d\n", callTime, enMmcLocation); + SLOGD("revBuf******\n %s \n*********************\n\n", ttyData); + count++; + if(count > 300) + { + MLOGE("timeout, enMmcLocation=%d\n", enMmcLocation); + count = 0; + return SF_4G_ERROR_AT_TIMEOUT; + } + } + + return ret; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/4gMng/sf_http_server.c b/code/application/source/sf_app/code/source/4gMng/sf_http_server.c new file mode 100755 index 000000000..0683984f6 --- /dev/null +++ b/code/application/source/sf_app/code/source/4gMng/sf_http_server.c @@ -0,0 +1,466 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" + +#include "cJSON.h" + +#include"sf_http_server.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +SINT32 socketfd = -1; + +SINT32 http_server_creat(char *host, int *sock) +{ + struct sockaddr_in address; + int clt_sock; + int opvalue = 8; + socklen_t slen; + int i=0; + int ret = 0; + + slen = sizeof(opvalue); + memset(&address, 0, sizeof(address)); + if ((clt_sock= socket(AF_INET, SOCK_STREAM, 0)) < 0 || + setsockopt(clt_sock, IPPROTO_IP, IP_TOS, &opvalue, slen) < 0) + { + MLOGE("socket socket error.\n"); + return -1; + } + struct timeval timeo = {120, 0}; + + setsockopt(clt_sock, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)); + setsockopt(clt_sock, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); + + + address.sin_family = AF_INET; + address.sin_port = htons((unsigned short)HTTP_PORT); + + struct hostent* server = gethostbyname(host); + if (!server) + { + MLOGE("dns error.\n"); + return -1; + } + + for(i = 0;server->h_addr_list[i];i++) + printf("...server ip addr%d: %s \n",i,inet_ntoa(*(struct in_addr*)server->h_addr_list[i])); + + address.sin_addr = *(struct in_addr *)server->h_addr_list[0]; + ret = connect(clt_sock, (struct sockaddr*)&address, sizeof(address)); + if (ret != 0) + { + MLOGE("socket socket connect error. ret = %d\n", ret); + return -1; + } + + *sock = clt_sock; + + return 0; +} +SINT32 http_send_to_server(int sock_fd, char *data, int length) +{ + int written_len = 0; + int writelen = 0; + int ret = 0; + +// MLOGD("lenth:%d\n", length); + while (written_len < length) + { + if(length - written_len > 1024*20) + writelen = 1024*20; + else + writelen = length - written_len; + +// MLOGD("written_len:%d,lenth:%d\n", written_len, length); + ret = send(sock_fd, data + written_len, writelen, 0); + if (ret > 0) + { + written_len += ret; +// MLOGD("written_len:%d,ret:%d\n", written_len,ret); + continue; + } + else if (ret == 0) + { +// MLOGD("written_len:%d,ret:%d\n", written_len,ret); + return written_len; + } + else + { + MLOGD("written_len:%d,ret:%d\n", written_len, ret); + MLOGE("HTTP Send:%d\n", ret); + return -1; /* Connnection error */ + } + } + + MLOGD("Send End,written_len:%d\n", written_len); + return SF_SUCCESS; +} + +SINT32 http_recv_from_server(int sock_fd, char *data, int length) +{ + SINT32 recv_byte = 0; + recv_byte = recv(sock_fd, data, length, 0); + if(recv_byte == 0) + { + sleep(3); + recv_byte = recv(sock_fd, data, length, 0); + } + return recv_byte; +} +SINT32 http_server_close(int sock_fd) +{ + return close(sock_fd); +} +static SINT32 http_response_status_code(char *data) +{ + char *p = NULL; + char ack[3] = {0}; + + p = strstr(data, "HTTP/1.1"); + memcpy(ack, p+9, 3); + switch(atoi(ack)/100) + { + case 1: + MLOGI(">>>information corresponding\n"); + return SF_SUCCESS; + case 2: + MLOGI(">>>successful response\n"); + return SF_SUCCESS; + case 3: + MLOGI(">>>redirect message\n"); + return SF_SUCCESS; + case 4: + MLOGE(">>>Client error response\n"); + return SF_FAILURE; + case 5: + MLOGE(">>>server error response\n"); + return SF_FAILURE; + default: + MLOGE(">>>undefined error response\n"); + return SF_FAILURE; + } + + return SF_SUCCESS; +} +static SINT32 http_authentication_parse(char *data,SF_PDT_PARAM_STATISTICS_S *pStaticParam) +{ + char *p = NULL; + char *out = NULL; + cJSON *json = NULL; + cJSON *first = NULL; + cJSON *second = NULL; + cJSON *subListItem = NULL; + SINT32 s32ret = SF_SUCCESS; + UINT16 index = 0; + SF_CHAR tempStr[128] = {0}; + SF_CHAR decode_tempStr[128] = {0}; + + s32ret = http_response_status_code(data); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_NO_SUPPORT); + + p = strchr(data, '{'); + json=cJSON_Parse(p); + if (!json) + { + SLOGE("Error before: [%s]\n",cJSON_GetErrorPtr()); + cJSON_Delete(json); + return SF_HTTP_ERROR_DATA_FORMAT; + } + + + first = cJSON_GetObjectItem(json, "statu"); + MLOGD("...code = %d\n", first->valueint); + first = cJSON_GetObjectItem(json, "errCode"); + MLOGD("...errCode = %d\n", first->valueint); + + if(first->valueint == 0) + { + first = cJSON_GetObjectItem(json, "msg"); + MLOGD("...msg = %s\n", first->valuestring); + first = cJSON_GetObjectItem(json, "content"); + out=cJSON_Print(first); + if(!strstr(out, "null")) + { + for(index = 0; index < 3; index++) + { + subListItem = cJSON_GetArrayItem(first, index); + if(cJSON_GetObjectItem(subListItem, "serverType")->valueSINT32 == 4) + { + second = cJSON_GetObjectItem(subListItem, "ip"); + memcpy(tempStr, second->valuestring, strlen(second->valuestring)); + + sf_base64_decode(tempStr, decode_tempStr); + + sprintf(pStaticParam->AcmIP, "%s", decode_tempStr); + MLOGD("AcmIP = %s\n", pStaticParam->AcmIP); + } + } + } + free(out); + } + else + { + s32ret = first->valueint; + if(first->valueint == SF_DEV_NOT_EXIST) + { + MLOGE("device does not exist\n"); + } + else if(first->valueint == SF_DEV_NOT_BIND) + { + MLOGE("Device not bound\n"); + } + } + + cJSON_Delete(json); + return s32ret; +} + +static SINT32 http_authentication_packet(SF_CHAR *data_buff,SF_PDT_PARAM_STATISTICS_S *pStaticParam) + +{ + memset(data_buff, '\0', strlen(data_buff)); + sprintf(data_buff, "POST /CameraManager/center/device/imeiAndMSisdn" + "?imei=%s&iccid=%s" + " HTTP/1.1\r\n" + "Host:%s\r\n" + "Connection: keep-alive\n" + "Content-Type: application/json\r\n\r\n",pStaticParam->IMEI, pStaticParam->SimID, pStaticParam->WebIP); + + #ifndef SF_VERSION_RELEASE + MLOGD("send_buff********\n%s\n", data_buff); + #endif + return SF_SUCCESS; + +} +static SINT32 http_domain_name_get(char *url, char *host) +{ + char *pA; + char *pB; + memset(host, 0, strlen(host)); + + if (!(*url)) + return -1; + + pA = url; + if (!strncmp(pA, "http://", strlen("http://"))) + pA = url + strlen("http://"); + else if (!strncmp(pA, "https://", strlen("https://"))) + pA = url + strlen("https://"); + + pB = strchr(pA, '/'); + + if (pB) + { + memcpy(host, pA, strlen(pA) - strlen(pB)); + host[strlen(pA) - strlen(pB)] = 0; + } + else + { + memcpy(host, pA, strlen(pA)); + host[strlen(pA)] = 0; + } +// SLOGD("host = %s\n", host); + + return 0; +} +static SINT32 http_pushfile_to_server(SINT32 socketfd, SF_FILE_ATTR_S *stFileAttr) +{ + SINT32 ret = SF_SUCCESS; + SINT32 fileFd = 0; + SINT32 tolFileSize = 0; + SINT32 readSize = 0; + struct stat statBuf; + SF_CHAR *pBuf = NULL; + SF_CHAR *bufBak = NULL; + + fileFd = open(stFileAttr->txtfilePath, O_RDONLY); + if(fileFd < 0) + { + SLOGE("open file[%s] error!\n", stFileAttr->txtfilePath); + return SF_FAILURE; + } + + fstat(fileFd, &statBuf); + tolFileSize = statBuf.st_size; + SLOGD("tolFileSize:%d\n", tolFileSize); + + bufBak = (tolFileSize > 1024*1024*5)?malloc(1024*1024*5):malloc(tolFileSize); + if(bufBak == NULL) + { + SLOGE("malloc buf fail!\n"); + close(fileFd); + return SF_FAILURE; + } + + while(tolFileSize > 0) + { + pBuf = bufBak; + readSize = (tolFileSize >= 1024*1024*5)?read(fileFd, pBuf, 1024*1024*5):read(fileFd, pBuf, tolFileSize); + SLOGD("send file data, tolFileSize:%d, read size:%d\n", tolFileSize, readSize); + tolFileSize -= readSize; + + if(readSize < 0) + { + free(bufBak); + close(fileFd); + return SF_FAILURE; + } + ret = http_send_to_server(socketfd, pBuf, readSize); + if (ret < 0) + { + SLOGE("Connection error (send returned %d)\n", ret); + free(bufBak); + close(fileFd); + return ret; + } + + } + + free(bufBak); + close(fileFd); + SLOGD("SF_SUCCESS!\n"); + return SF_SUCCESS; +} +static SINT32 http_file_response_parse() +{ + return SF_SUCCESS; +} + +SINT32 sf_usbnet_http_authenrequst(SF_PDT_PARAM_STATISTICS_S *pStaticParam) + { + SF_COMM_CHECK_POINTER(pStaticParam,SF_FAILURE); + + SINT32 s32ret = 0; + SINT32 recv_byte = 0; + SINT32 sock_cli = 0; + SF_CHAR data_buff[BUFFER_SIZE] = { 0 }; + + MLOGD("WebIP:%s\n", pStaticParam->WebIP); + s32ret = http_server_creat(pStaticParam->WebIP, &sock_cli); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = http_authentication_packet(data_buff,pStaticParam); + if(s32ret !=SF_SUCCESS) { + close(sock_cli); + return SF_HTTP_ERROR_REQUEST; + } + + s32ret = http_send_to_server(sock_cli,data_buff,strlen(data_buff)); + if(s32ret < SF_SUCCESS) { + close(sock_cli); + return SF_HTTP_ERROR_REQUEST; + } + + memset(data_buff, '\0', sizeof(data_buff)); + http_recv_from_server(sock_cli,data_buff,BUFFER_SIZE); + + s32ret = http_authentication_parse(data_buff, pStaticParam); + if(s32ret != SF_SUCCESS) { + close(sock_cli); + return SF_HTTP_ERROR_REQUEST; + } + close(sock_cli); + + return s32ret; +} +SINT32 sf_usbnet_http_pushfile(SF_FILE_ATTR_S *pstFileAttr,SF_FN_PARAM_S *pfnParam) +{ + SINT32 s32ret = SF_SUCCESS; + SINT32 socketfd = -1; + SF_CHAR amzIP[128] = {0}; + SF_CHAR buf[HTTPCLIENT_REV_SIZE] = {0}; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + + sprintf(amzIP, "%s.%s", pStaticParam->stOssCfg.szBucket, AMZ_HOST); + MLOGI("login [%s]\n",amzIP); + s32ret = http_server_creat(amzIP,&socketfd); + if(s32ret != SF_SUCCESS) { + MLOGE("login [%s] failed\n",amzIP); + return SF_FAILURE; + } + + s32ret = http_pushfile_to_server(socketfd,pstFileAttr); + if(s32ret != SF_SUCCESS) { + http_server_close(socketfd); + MLOGE("push file failed!!!\n"); + return SF_FAILURE; + } + + s32ret = http_recv_from_server(socketfd, buf, HTTPCLIENT_REV_SIZE); + if(s32ret <= 0) + { + SLOGE("recv innormal!!!"); + http_server_close(socketfd); + return SF_FAILURE; + } + //http_file_response_parse(); + MLOGD("recv buf:%s\n", buf); + http_server_close(socketfd); + return SF_SUCCESS; +} + +int sf_usbnet_server_acm_open(SF_PDT_PARAM_STATISTICS_S *pStaticParam) +{ + int ret = 0; + SF_CHAR server_domain_name[32] = {0}; + ret = http_domain_name_get(pStaticParam->AcmIP,server_domain_name); + if(ret != SF_SUCCESS) + return ret; + MLOGI("acm domain name:[%s]\n",server_domain_name ); + ret = http_server_creat(server_domain_name, &socketfd); + if(ret != SF_SUCCESS) + return ret; + + return SF_SUCCESS; +} +SINT32 sf_usbnet_server_acm_transfer(SF_DATA_ATTR_S *psenddate) +{ + SINT32 s32ret = 0; + + s32ret = http_send_to_server(socketfd,(char*)psenddate->databuf,psenddate->dataSize); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_WRITE); + + + memset(psenddate->databuf, '\0', SF_HTTP_RECV_MAX); + s32ret = http_recv_from_server(socketfd,(char*)psenddate->databuf, SF_HTTP_RECV_MAX); + MLOGI("datasize = %d\n",s32ret); + if(s32ret <= 0) + return SF_FAILURE; + psenddate->dataSize = s32ret; + return SF_SUCCESS; +} + +SINT32 sf_usbnet_server_acm_close() +{ + MLOGI("\n"); + return http_server_close(socketfd); + +} + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/4gMng/sf_module.c b/code/application/source/sf_app/code/source/4gMng/sf_module.c new file mode 100755 index 000000000..0cd9e09b7 --- /dev/null +++ b/code/application/source/sf_app/code/source/4gMng/sf_module.c @@ -0,0 +1,305 @@ +#include +#include +#include +#include +#include +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_log.h" +#include "sf_type.h" +#include "sf_hal_gpio.h" +#include "sf_module.h" +#if defined(CFG_MODULE_EG91) +#include "sf_eg91_sim.h" +#include "sf_eg91_gps.h" +#include "sf_eg91_server.h" +#ifndef CFG_TRANSDATA_AT +#include "sf_http_server.h" +#endif +#endif +extern pthread_mutex_t GPIO_mutexLock; + +static SF_4G_STATUS_E ModuleStatus = SF_4G_FREE; + +void sf_4G_usb_init(void) +{ + sf_hal_gpio_init(GPIOID_USB_MUX1,GPIO_DIR_OUT); + sf_hal_gpio_set(GPIOID_USB_MUX1,1); +} +SF_4G_STATUS_E sf_4G_status_get(void) +{ + return ModuleStatus; +} + +void sf_4G_status_set(SF_4G_STATUS_E enStatus) +{ + + if(enStatus < SF_4G_BUTT) + ModuleStatus = enStatus; + else + MLOGE("Type format error\n"); + + return; +} + +SINT32 sf_4G_sim_IsInsert(void) +{ + return 1; + SINT8 regValue = 0; + SF_MUTEX_LOCK(GPIO_mutexLock); + sf_hal_gpio_init(GPIOID_SIM_INSRET, GPIO_DIR_IN); + sf_hal_gpio_get(GPIOID_SIM_INSRET, ®Value); + sf_hal_gpio_deinit(GPIOID_SIM_INSRET); + SF_MUTEX_UNLOCK(GPIO_mutexLock); + MLOGI("SIM = %d\n",regValue); + return (regValue & 0xFF) ? 1:0; + +} + +static UINT8 sf_4g_net_level_get(UINT8 simSignal) +{ + if(simSignal == 0) + { + return 0; + } + else if((simSignal <= 95) && (simSignal > 0)) + { + return 4; + } + else if((simSignal <= 105) && (simSignal > 95)) + { + return 3; + } + else if((simSignal <= 115) && (simSignal > 105)) + { + return 3; + } + else if((simSignal > 115)) + return 2; + + + return SF_SUCCESS; +} + +static UINT8 sf_3g_net_level_get(UINT8 simSignal) +{ + if(simSignal == 0) + { + return 0; + } + else if(simSignal < 10) + { + return 2; + } + else if(simSignal < 14) + { + return 3;//t100, custumer signal level,20210914 + } + else if(simSignal < 18) + { + return 3;//t100, custumer signal level,20210914 + } + else if(simSignal <= 31) + { + return 4;//t100, custumer signal level,20210914 + } + return SF_SUCCESS; + +} + + +SINT32 sf_4G_signal_level_get(SINT8 net,SINT8 signal,UINT8* value) +{ + SF_COMM_CHECK_POINTER(value,SF_FAILURE); + + if(net == 4) + *value = sf_4g_net_level_get(signal); + else + *value = sf_3g_net_level_get(signal); + + + return SF_SUCCESS; +} + +SINT32 sf_4G_qsclk_set(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_qsclk_set(pfnParam); + #endif +} +SINT32 sf_4G_iccid_get(SF_CHAR *iccid,SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_iccid_get(iccid,pfnParam); + #endif +} +SINT32 sf_4G_http_config(SF_FN_PARAM_S *pfnParam, UINT8 sslOn, UINT8 autoReqHead) +{ + #if defined(CFG_MODULE_EG91) + return eg91_http_config(pfnParam,sslOn,autoReqHead); + #endif +} + +SINT32 sf_4G_http_authenrequst(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + #if defined(CFG_TRANSDATA_AT) + return eg91_http_authenrequst(pfnParam); + #else + return sf_usbnet_http_authenrequst(pfnParam->pstaticParam); + #endif + #endif +} + +SINT32 sf_4G_file_transfer(SF_CHAR *fileName, SINT32 *fileSize, SF_FILE_TYPE_E fileType) +{ + #if defined(CFG_MODULE_EG91) + #if defined(CFG_TRANSDATA_AT) + return eg91_file_to_module(fileName, fileSize,fileType); + #else + return SF_SUCCESS; + #endif + #endif +} + +SINT32 sf_4G_http_pushfile(SF_FILE_ATTR_S *pstFileAttr,SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + #if defined(CFG_TRANSDATA_AT) + return eg91_http_pushfile(pstFileAttr,pfnParam); + #else + return sf_usbnet_http_pushfile(pstFileAttr,pfnParam); + #endif + #endif +} +SINT32 sf_4G_server_open(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + + #if defined(CFG_TRANSDATA_AT) + return eg91_server_acm_open(pfnParam); + #else + return sf_usbnet_server_acm_open(pfnParam->pstaticParam); + #endif + #endif +} + +SINT32 sf_4G_acm_tcp_server_open(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_server_acm_open(pfnParam); + #endif +} + +SINT32 sf_4G_acm_tcp_server_close(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_server_acm_close(pfnParam); + #endif +} + +SINT32 sf_4G_server_transferdata(SF_DATA_ATTR_S *psenddate, SF_FN_PARAM_S *pfnParam, UINT8 needRepose) +{ + #if defined(CFG_MODULE_EG91) + #if defined(CFG_TRANSDATA_AT) + return eg91_server_acm_transfer(psenddate, pfnParam, needRepose); + #else + return sf_usbnet_server_acm_transfer(psenddate); + #endif + #endif +} + +SINT32 sf_4G_acm_tcp_server_transferdata(SF_DATA_ATTR_S *psenddate, SF_FN_PARAM_S *pfnParam, UINT8 needRepose) +{ + #if defined(CFG_MODULE_EG91) + return eg91_server_acm_transfer(psenddate, pfnParam, needRepose); + #endif +} + +SINT32 sf_4G_server_close(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + #if defined(CFG_TRANSDATA_AT) + return eg91_server_acm_close(pfnParam); + #else + return sf_usbnet_server_acm_close(); + #endif + #endif +} +SINT32 sf_4G_gps_greendate_Get(SF_FN_PARAM_S *pfnParam,SF_PARA_TIME_S *pNowTime) +{ + #if defined(CFG_MODULE_EG91) + return eg91_gps_greendate_Get(pfnParam,pNowTime); + #endif +} + +SINT32 sf_4G_gps_Isupdate(SF_FN_PARAM_S *pfnParam,UINT8 *pIsupdate,SF_PARA_TIME_S *pNowTime,UINT8 u8day) +{ + #if defined(CFG_MODULE_EG91) + return eg91_gps_Isupdate(pfnParam,pIsupdate,pNowTime,u8day); + #endif +} +SINT32 sf_4G_gps_preconfig(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_gps_preconfig(pfnParam); + #endif +} + +SINT32 sf_4G_gps_search(SF_FN_PARAM_S *pfnParam,SF_PARA_TIME_S *pNowTime,UINT8 autoModeFlag) +{ + #if defined(CFG_MODULE_EG91) + return eg91_gps_search(pfnParam,pNowTime,autoModeFlag); + #endif +} +SINT32 sf_4G_gps_search_result(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_gps_search_result(pfnParam); + #endif +} + +SINT32 sf_4G_sim_init(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_sim_init(pfnParam); + #endif +} +SINT32 sf_4G_register_net_manual(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_register_net_manual(pfnParam); + #endif +} +SINT32 sf_4G_register_net_auto(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_register_net_auto(pfnParam); + #endif +} + +SINT32 sf_4G_usb_net_apn_cfg(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_usb_net_apn_cfg(pfnParam); + #endif +} +SINT32 sf_4G_other_sim_apn_cfg(SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_MODULE_EG91) + return eg91_other_sim_apn_cfg(pfnParam->pstaticParam); + #endif +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + diff --git a/code/application/source/sf_app/code/source/4gMng/sf_opera_adapt.c b/code/application/source/sf_app/code/source/4gMng/sf_opera_adapt.c new file mode 100755 index 000000000..7d1953ef0 --- /dev/null +++ b/code/application/source/sf_app/code/source/4gMng/sf_opera_adapt.c @@ -0,0 +1,1703 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: Oliver + * + * Ver: 1.0.0 2018/5/7 + * Ver: 1.0.1 2018/8/6: Oliver + * Ver: 1.1.0 2018/8/6: Oliver + * Ver: 1.1.1 2018/8/8: Oliver + * Ver: 1.1.2 2018/8/9: Will + * Ver: 1.1.3 2018/11/7: Will-Add Ukraine Italy Spain (AT@T Modify) +**************************************************************************/ +#include +#include "sf_type.h" +#include "sf_log.h" + +#include "sf_opera_adapt.h" +#include "sf_hal_ttyusb.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MMS_SET (0) + +UINT16 sf_auto_operation_adaptation(SF_CHAR *operatorName, SF_PDT_PARAM_STATISTICS_S *sim_info_t) +{ + MLOGD("Auto_Operation_Adjust NEW, Name:%s\n", operatorName); + if((strncmp(operatorName, "46001", 5) == 0) || (strncmp(operatorName, "46010", 5) == 0)) //china union + { + //SMTP,FTP SET + strcpy(sim_info_t->ApnGPRS, "3gnet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + //LOGI("Auto_Operation_Adjust NEW, ApnGPRS:%s\n", sim_info_t->ApnGPRS); + #if MMS_SET + //MMS SET + strcpy(puiPara->APNMMS, "3gwap"); + strcpy(puiPara->URL, "http://mmsc.myuni.com.cn"); + strcpy(puiPara->IP, "10.0.0.172"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + + } + else if((strncmp(operatorName, "46000", 5) == 0) || (strncmp(operatorName, "46002", 5) == 0) || (strncmp(operatorName, "46004", 5) == 0) || (strncmp(operatorName, "46007", 5) == 0))//china union + { + strcpy(sim_info_t->ApnGPRS, "CMNET"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "CMWAP"); + strcpy(puiPara->URL, "mmsc.monternet.com"); + strcpy(puiPara->IP, "10.0.0.172"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "46003", 5) == 0) || (strncmp(operatorName, "46005", 5) == 0) || (strncmp(operatorName, "46011", 5) == 0))//china telcom + { + strcpy(sim_info_t->ApnGPRS, "CTNET"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "CTWAP"); + strcpy(puiPara->URL, "http://mmsc.vnet.mobi"); + strcpy(puiPara->IP, "10.0.0.200"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "31000", 5) == 0) || (strncmp(operatorName, "31001", 5) == 0) || (strncmp(operatorName, "31059", 5) == 0) + || (strncmp(operatorName, "31089", 5) == 0) || (strncmp(operatorName, "31091", 5) == 0) || (strncmp(operatorName, "31111", 5) == 0) + || (strncmp(operatorName, "31127", 5) == 0) || (strncmp(operatorName, "31128", 5) == 0) || (strncmp(operatorName, "31139", 5) == 0) + || (strncmp(operatorName, "31148", 5) == 0)) //Vierzon + { + strcpy((char *)sim_info_t->ApnGPRS, "vzwinternet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy((char *)puiPara->MmsApn, "\0"); + strcpy((char *)puiPara->MmsMmsc, "\0"); + strcpy((char *)puiPara->MmsProxy, "\0"); + strcpy((char *)puiPara->MmsPort, "\0"); + strcpy((char *)puiPara->MmsUserName, "\0"); + strcpy((char *)puiPara->MmsPassword, "\0"); + #endif + } + else if((strncmp(operatorName, "50501", 5) == 0) || (strncmp(operatorName, "50511", 5) == 0) || (strncmp(operatorName, "50571", 5) == 0) || (strncmp(operatorName, "50572", 5) == 0))//australia telstra + { + strcpy(sim_info_t->ApnGPRS, "telstra.internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "telstra.mms"); + strcpy(puiPara->URL, "http://mmsc.telstra.com:8002"); + strcpy(puiPara->IP, "10.1.1.180"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21910", 5) == 0) //Croatia VIPnet + { + strcpy(sim_info_t->ApnGPRS, "data.vip.hr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.vipnet.hr"); + strcpy(puiPara->URL, "http://mms.vipnet.hr/servlets/mms"); + strcpy(puiPara->IP, "212.91.99.91"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21901", 5) == 0) //Croatia T-Mobile + { + strcpy(sim_info_t->ApnGPRS, "internet.ht.hr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.htgprs"); + strcpy(puiPara->URL, "http://mms.t-mobile.hr/servlets/mms"); + strcpy(puiPara->IP, "10.12.0.4"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21902", 5) == 0) // Croatia Tele2 + { + strcpy(sim_info_t->ApnGPRS, "internet.tele2.hr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "internet.tele2.hr"); + strcpy(puiPara->URL, "http://mmsc.tele2.hr"); + strcpy(puiPara->IP, "193.12.40.66"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "23820", 5) == 0) || (strncmp(operatorName, "23830", 5) == 0))//Danmark Telia + { + strcpy(sim_info_t->ApnGPRS, "www.internet.mtelia.dk"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "www.mms.mtelia.dk"); + strcpy(puiPara->URL, "www.mms.mtelia.dk"); + strcpy(puiPara->IP, "139.209.134.131"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23801", 5) == 0) //TDC + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://192.168.241.114:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "194.182.251.15"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23802", 5) == 0) //Telenor + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.telenor.dk"); + strcpy(puiPara->APNMMS, "internet"); + strcpy(puiPara->IP, "212.88.64.8"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23806", 5) == 0) //Oister + { + strcpy(sim_info_t->ApnGPRS, "Data.dk"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.oister.dk"); + strcpy(puiPara->APNMMS, "mmssp"); + strcpy(puiPara->IP, "172.16.53.12"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + + } + else if(strncmp(operatorName, "24603", 5) == 0)//Lithuania Tele 2 + { + strcpy(sim_info_t->ApnGPRS, "internet.tele2.lt"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.tele2.lt"); + strcpy(puiPara->URL, "http://mmsc.tele2.lt"); + strcpy(puiPara->IP, "193.12.40.29"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24602", 5) == 0)//Lithuania BITE + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://mmsc/servlets/mms"); + strcpy(puiPara->IP, "192.168.150.2"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms@mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "24601", 5) == 0)//Lithuania Omnitel + { + strcpy(sim_info_t->ApnGPRS, "omnitel"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "gprs.mms.lt"); + strcpy(puiPara->URL, "http://mms.omnitel.net:8002/"); + strcpy(puiPara->IP, "194.176.32.149"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "53001", 5) == 0)//New Zealand Vodafone + { + strcpy(sim_info_t->ApnGPRS, "vodafone"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "live.vodafone.com"); + strcpy(puiPara->URL, "http://pxt.vodafone.net.nz/pxtsend"); + strcpy(puiPara->IP, "172.30.38.3"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "53024", 5) == 0)//New Zealand Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://mms.2degreesmobile.net.nz:48090"); + strcpy(puiPara->IP, "118.148.1.118"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22610", 5) == 0)// Romania Orange + { + strcpy(sim_info_t->ApnGPRS, "net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://wap.mms.orange.ro:8002"); + strcpy(puiPara->IP, "62.217.247.252"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "22601", 5) == 0)// Romania Vodafone + { + strcpy(sim_info_t->ApnGPRS, "live.vodafone.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22603", 5) == 0)// Romania Romtelecom + { + strcpy(sim_info_t->ApnGPRS, "broadband"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22605", 5) == 0)// Romania DIGI.mobil + { + strcpy(sim_info_t->ApnGPRS, "prepaid"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "25028", 5) == 0) || (strncmp(operatorName, "25099", 5) == 0))// Russian Federation Beeline + { + strcpy(sim_info_t->ApnGPRS, "internet.beeline.ru"); + strcpy(sim_info_t->ApnUsername, "beeline"); + strcpy(sim_info_t->ApnPassword, "beeline"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.beeline.ru"); + strcpy(puiPara->URL, "http://mmsc/"); + strcpy(puiPara->IP, "192.168.94.23"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "beeline"); + strcpy(puiPara->PASSWORD, "beeline"); + #endif + } + else if(strncmp(operatorName, "25001", 5) == 0)// Russian Federation MTS + { + strcpy(sim_info_t->ApnGPRS, "internet.mts.ru"); + strcpy(sim_info_t->ApnUsername, "mts"); + strcpy(sim_info_t->ApnPassword, "mts"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.mts.ru"); + strcpy(puiPara->URL, "http://mmsc"); + strcpy(puiPara->IP, "192.168.192.192"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mts"); + strcpy(puiPara->PASSWORD, "mts"); + #endif + } + else if(strncmp(operatorName, "25002", 5) == 0)// Russian Federation MegaFon + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "gdata"); + strcpy(sim_info_t->ApnPassword, "gdata"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "http://mmsc:8002"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "gdata"); + strcpy(puiPara->PASSWORD, "gdata"); + #endif + } + else if(strncmp(operatorName, "25020", 5) == 0)// Russian Federation Tele2 + { + strcpy(sim_info_t->ApnGPRS, "internet.tele2.ru"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.tele2.ru"); + strcpy(puiPara->URL, "http://mmsc.tele2.ru"); + strcpy(puiPara->IP, "193.12.40.65"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25011", 5) == 0)// Russian Federation Yota + { + strcpy(sim_info_t->ApnGPRS, "internet.yota"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.yota"); + strcpy(puiPara->URL, "http://mmsc:8002"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25035", 5) == 0)// Russian Federation Motiv + { + strcpy(sim_info_t->ApnGPRS, "inet.ycc.ru"); + strcpy(sim_info_t->ApnUsername, "motiv"); + strcpy(sim_info_t->ApnPassword, "motiv"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.ycc.ru"); + strcpy(puiPara->URL, "http://mms.ycc.ru"); + strcpy(puiPara->IP, "172.16.2.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "motiv"); + strcpy(puiPara->PASSWORD, "motiv"); + #endif + } + else if(strncmp(operatorName, "24007", 5) == 0)//Sweden Tele2 COMVIQ + { + strcpy(sim_info_t->ApnGPRS, "4G.tele2.se"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.tele2.se"); + strcpy(puiPara->APNMMS, "4G.tele2.se"); + strcpy(puiPara->IP, "130.244.202.30"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24001", 5) == 0)//Sweden TeliaSonera Mobile + { + strcpy(sim_info_t->ApnGPRS, "online.telia.se"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmss"); + strcpy(puiPara->APNMMS, "mms.telia.se"); + strcpy(puiPara->IP, "193.209.134.132"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "telia"); + #endif + } + else if((strncmp(operatorName, "24006", 5) == 0) || (strncmp(operatorName, "24008", 5) == 0) || (strncmp(operatorName, "24024", 5) == 0))//Sweden Telenor Mobile Sverige + { + strcpy(sim_info_t->ApnGPRS, "services.telenor.se"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "services.telenor.se"); + strcpy(puiPara->IP, "172.30.253.241"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "23433", 5) == 0) || (strncmp(operatorName, "23434", 5) == 0))// United Kingdom Orange + { + strcpy(sim_info_t->ApnGPRS, "orangeinternet"); + strcpy(sim_info_t->ApnUsername, "user"); + strcpy(sim_info_t->ApnPassword, "pass"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "orangemms"); + strcpy(puiPara->URL, "http://mms.orange.co.uk/"); + strcpy(puiPara->IP, "192.168.224.10"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "Orange"); + strcpy(puiPara->PASSWORD, "Multimedia"); + #endif + } + + else if((strncmp(operatorName, "23402", 5) == 0) || (strncmp(operatorName, "23410", 5) == 0) || (strncmp(operatorName, "23411", 5) == 0))// United Kingdom O2 + { + strcpy(sim_info_t->ApnGPRS, "mobile.o2.co.uk"); + strcpy(sim_info_t->ApnUsername, "web"); + strcpy(sim_info_t->ApnPassword, "password"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "payandgo.o2.co.uk"); + strcpy(puiPara->URL, "http://mmsc.mms.o2.co.uk:8002"); + strcpy(puiPara->IP, "193.113.200.195"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "payandgo"); + strcpy(puiPara->PASSWORD, "password"); + #endif + } + else if(strncmp(operatorName, "23415", 5) == 0)//United Kingdom Vodafone + { + strcpy(sim_info_t->ApnGPRS, "pp.vodafone.co.uk"); + strcpy(sim_info_t->ApnUsername, "web"); + strcpy(sim_info_t->ApnPassword, "web"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "wap.vodafone.co.uk"); + strcpy(puiPara->URL, "http://mms.vodafone.co.uk/servlets/mms/"); + strcpy(puiPara->IP, "212.183.137.12"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "wap"); + strcpy(puiPara->PASSWORD, "wap"); + #endif + } + else if(strncmp(operatorName, "23430", 5) == 0)//United Kingdom T-Mobile + { + strcpy(sim_info_t->ApnGPRS, "general.t-mobile.uk"); + strcpy(sim_info_t->ApnUsername, "user"); + strcpy(sim_info_t->ApnPassword, "wap"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "general.t-mobile.uk"); + strcpy(puiPara->URL, "http://mmsc.t-mobile.co.uk:8002/"); + strcpy(puiPara->IP, "149.254.211.10"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "user"); + strcpy(puiPara->PASSWORD, "one2one"); + #endif + } + else if(strncmp(operatorName, "23420", 5) == 0)//United Kingdom 3 + { + strcpy(sim_info_t->ApnGPRS, "three.co.uk"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.three.co.uk"); + strcpy(puiPara->URL, "http://mms.um.three.co.uk:10021/mmsc"); + strcpy(puiPara->IP, "217.171.129.2"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "24403", 5) == 0) || (strncmp(operatorName, "24412", 5) == 0))// Finland DNA + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.dnafinland.fi"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.1.1.2"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24421", 5) == 0)// Finland Saunalahti + { + strcpy(sim_info_t->ApnGPRS, "internet.saunalahti"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.saunalahti.fi:8002/"); + strcpy(puiPara->APNMMS, "mms.saunalahti.fi"); + strcpy(puiPara->IP, "62.142.4.197"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24405", 5) == 0)// Finland Elisa + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.elisa.fi"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.161.41.57"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24491", 5) == 0)// Finland Sonera + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.sonera.net:8002/"); + strcpy(puiPara->APNMMS, "wap.sonera.net"); + strcpy(puiPara->IP, "195.156.25.33"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "24410", 5) == 0)// Finland TDC + { + strcpy(sim_info_t->ApnGPRS, "inet.tdc.fi"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.tdc.fi"); + strcpy(puiPara->APNMMS, "mms.tdc.fi"); + strcpy(puiPara->IP, "10.1.12.2"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65507", 5) == 0)// South Africa Cell C + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.cmobile.co.za/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "196.31.116.250"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65510", 5) == 0)// South Africa MTN + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "guest"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.mtn.co.za/mms/wapenc"); + strcpy(puiPara->APNMMS, "mymtn"); + strcpy(puiPara->IP, "196.11.240.241"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65501", 5) == 0)// South Africa Vodacom + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "guest"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.vodacom4me.co.za/"); + strcpy(puiPara->APNMMS, "mms.vodacom.net"); + strcpy(puiPara->IP, "196.6.128.13"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "65502", 5) == 0)// South Africa 8ta + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "guest"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.8ta.com:38090/was"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "41.151.254.162"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "guest"); + strcpy(puiPara->PASSWORD, "guest"); + #endif + } + else if(strncmp(operatorName, "22201", 5) == 0)// Italy TIM + { + strcpy(sim_info_t->ApnGPRS, "ibox.tim.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.tim.it/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.tim.it"); + strcpy(puiPara->IP, "213.230.130.89"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22210", 5) == 0)// Italy Vodafone + { + strcpy(sim_info_t->ApnGPRS, "mobile.vodafone.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.vodafone.it/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.vodafone.it"); + strcpy(puiPara->IP, "10.128.224.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22288", 5) == 0)// Italy wind + { + strcpy(sim_info_t->ApnGPRS, "internet.wind"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.wind.it"); + strcpy(puiPara->APNMMS, "mms.wind"); + strcpy(puiPara->IP, "212.245.244.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22208", 5) == 0) //Italy Fastweb Mobile + { + strcpy(sim_info_t->ApnGPRS, "apn.fastweb.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22207", 5) == 0) //Italy Kena Mobile + { + strcpy(sim_info_t->ApnGPRS, "web.kenamobile.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22215", 5) == 0) //Italy Iliad + { + strcpy(sim_info_t->ApnGPRS, "iliad"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "22233", 5) == 0) //Italy PosteMobile + { + strcpy(sim_info_t->ApnGPRS, "wap.postemobile.it"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20815", 5) == 0)// France Free Mobile + { + strcpy(sim_info_t->ApnGPRS, "free"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.free.fr"); + strcpy(puiPara->APNMMS, "mmsfree"); + strcpy(puiPara->IP, "212.27.40.225"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20801", 5) == 0) // France Orange + { + strcpy(sim_info_t->ApnGPRS, "orange"); + strcpy(sim_info_t->ApnUsername, "orange"); + strcpy(sim_info_t->ApnPassword, "orange"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.orange.fr"); + strcpy(puiPara->APNMMS, "orange.acte"); + strcpy(puiPara->IP, "192.168.10.200"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20820", 5) == 0)// France Bouygues Telecom + { + strcpy(sim_info_t->ApnGPRS, "mmsbouygtel.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.bouyguestelecom.fr/mms/wap"); + strcpy(puiPara->APNMMS, "mmsbouygtel.com"); + strcpy(puiPara->IP, "62.201.137.17"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20810", 5) == 0)// France SFR + { + strcpy(sim_info_t->ApnGPRS, "sl2sfr"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms1"); + strcpy(puiPara->APNMMS, "sl2sfr"); + strcpy(puiPara->IP, "10.151.0.1"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "31003", 5) == 0) || (strncmp(operatorName, "31009", 5) == 0) \ + || (strncmp(operatorName, "31015", 5) == 0) || (strncmp(operatorName, "31017", 5) == 0) \ + || (strncmp(operatorName, "31041", 5) == 0) || (strncmp(operatorName, "31056", 5) == 0) \ + || (strncmp(operatorName, "31068", 5) == 0) || (strncmp(operatorName, "31028", 5) == 0))// United States AT&T + { + strcpy(sim_info_t->ApnGPRS, "nxtgenphone"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.mobile.att.net"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "proxy.mobile.att.net"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + + else if((strncmp(operatorName, "31002", 5) == 0) || (strncmp(operatorName, "31016", 5) == 0) || (strncmp(operatorName, "31020", 5) == 0)|| (strncmp(operatorName, "31021", 5) == 0)|| (strncmp(operatorName, "31022", 5) == 0)|| (strncmp(operatorName, "31023", 5) == 0)|| (strncmp(operatorName, "31024", 5) == 0) + + || (strncmp(operatorName, "31025", 5) == 0) || (strncmp(operatorName, "31026", 5) == 0) || (strncmp(operatorName, "31027", 5) == 0) || (strncmp(operatorName, "31029", 5) == 0) || (strncmp(operatorName, "31031", 5) == 0) || (strncmp(operatorName, "31033", 5) == 0) + || (strncmp(operatorName, "31058", 5) == 0) || (strncmp(operatorName, "31066", 5) == 0) || (strncmp(operatorName, "31080", 5) == 0))// United States T-Mobile + { + strcpy(sim_info_t->ApnGPRS, "fast.t-mobile.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.msg.eng.t-mobile.com/mms/wapenc"); + strcpy(puiPara->APNMMS, "wap.voicestream.com"); + strcpy(puiPara->IP, "216.155.165.50"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if ((strncmp(operatorName, "26206", 5) == 0) || (strncmp(operatorName, "26212", 5) == 0)) + { + // Germany Telekom + strcpy(sim_info_t->ApnGPRS, "internet.telekom"); + strcpy(sim_info_t->ApnUsername, "t-mobile"); + strcpy(sim_info_t->ApnPassword, "tm"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.t-mobile.de/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.t-d1.de"); + strcpy(puiPara->IP, "172.28.23.131"); + strcpy(puiPara->PORT, "8008"); + strcpy(puiPara->USERNAME, "t-mobile"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "26201", 5) == 0) + { + // Germany T-Mobile + strcpy(sim_info_t->ApnGPRS, "internet.t-mobile"); + strcpy(sim_info_t->ApnUsername, "t-mobile"); + strcpy(sim_info_t->ApnPassword, "tm"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.t-mobile.de/servlets/mms"); + strcpy(puiPara->APNMMS, "internet.t-mobile"); + strcpy(puiPara->IP, "172.28.23.131"); + strcpy(puiPara->PORT, "8008"); + strcpy(puiPara->USERNAME, "t-mobile"); + strcpy(puiPara->PASSWORD, "tm"); + #endif + } + else if ((strncmp(operatorName, "26202", 5) == 0) || (strncmp(operatorName, "26204", 5) == 0) || (strncmp(operatorName, "26209", 5) == 0)) + { + // Germany Vodafone + strcpy(sim_info_t->ApnGPRS, "web.vodafone.de"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://139.7.24.1/servlets/mms"); + strcpy(puiPara->APNMMS, "event.vodafone.de"); + strcpy(puiPara->IP, "139.7.29.17"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "26203", 5) == 0) || (strncmp(operatorName, "26205", 5) == 0) || (strncmp(operatorName, "26277", 5) == 0)) + { + // Germany E-Plus + strcpy(sim_info_t->ApnGPRS, "internet.eplus.de"); + strcpy(sim_info_t->ApnUsername, "eplus"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms/eplus"); + strcpy(puiPara->APNMMS, "mms.eplus.de"); + strcpy(puiPara->IP, "212.23.97.153"); + strcpy(puiPara->PORT, "5080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "eplus"); + #endif + } + else if ((strncmp(operatorName, "26207", 5) == 0) || (strncmp(operatorName, "26208", 5) == 0) || (strncmp(operatorName, "26211", 5) == 0)) + { + // Germany O2 + strcpy(sim_info_t->ApnGPRS, "pinternet.interkom.de"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://10.81.0.7:8002/"); + strcpy(puiPara->APNMMS, "pinternet.interkom.de"); + strcpy(puiPara->IP, "82.113.100.6"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "29331", 5) == 0) || (strncmp(operatorName, "29341", 5) == 0) || (strncmp(operatorName, "29351", 5) == 0)) + { + // Slovenia Telekom + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "mobitel"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.telekom.si"); + strcpy(puiPara->APNMMS, "internet"); + strcpy(puiPara->IP, "213.229.249.40"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mobitel"); + strcpy(puiPara->PASSWORD, "internet"); + #endif + } + else if (strncmp(operatorName, "29340", 5) == 0) + { + // Slovenia Simobil + strcpy(sim_info_t->ApnGPRS, "internet.simobil.si"); + strcpy(sim_info_t->ApnUsername, "simobil"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmc"); + strcpy(puiPara->APNMMS, "mms.simobil.si"); + strcpy(puiPara->IP, "80.95.224.46"); + strcpy(puiPara->PORT, "9201"); + strcpy(puiPara->USERNAME, "simobil"); + strcpy(puiPara->PASSWORD, "internet"); + #endif + } + else if (strncmp(operatorName, "29364", 5) == 0) + { + // Slovenia T2 + strcpy(sim_info_t->ApnGPRS, "mms.t-2.net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://www.mms.t-2.net:8002"); + strcpy(puiPara->APNMMS, "mms.t-2.net"); + strcpy(puiPara->IP, "172.20.18.137"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "23106", 5) == 0) + { + //Slovakia O2 + strcpy(sim_info_t->ApnGPRS, "o2internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.o2world.sk:8002"); + strcpy(puiPara->APNMMS, "o2mms"); + strcpy(puiPara->IP, "10.97.1.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if ((strncmp(operatorName, "23102", 5) == 0) || (strncmp(operatorName, "23104", 5) == 0)) + { + //Slovakia T-Mobile + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.1.1"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "23101", 5) == 0) + { + //Slovakia Orange + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://imms.orange.sk"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.151.208.145"); + strcpy(puiPara->PORT, "8799"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "23103", 5) == 0) + { + //Slovakia 4Ka + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.1.1"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "42501", 5) == 0) + { + //Israel orange + strcpy(sim_info_t->ApnGPRS, "uinternet"); + strcpy(sim_info_t->ApnUsername, "orange"); + strcpy(sim_info_t->ApnPassword, "orange"); + + #if MMS_SET + strcpy(puiPara->URL, "http://192.168.220.15/servlets/mms"); + strcpy(puiPara->APNMMS, "uwap.orange.co.il"); + strcpy(puiPara->IP, "192.118.11.55"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24801", 5) == 0) + { + //Estonia(Telia) + strcpy(sim_info_t->ApnGPRS, "internet.emt.ee"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.emt.ee"); + strcpy(puiPara->URL, "mms.emt.ee/servlets/mms"); + strcpy(puiPara->IP, "217.71.32.82"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24802", 5) == 0) + { + //Estonia(Elisa) + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->URL, "194.204.2.10"); + strcpy(puiPara->IP, "194.204.2.6"); + strcpy(puiPara->PORT, "8000"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24803", 5) == 0) + { + //Estonia(Tele2) + strcpy(sim_info_t->ApnGPRS, "internet.tele2.ee"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->APNMMS, "mms.tele2.ee"); + strcpy(puiPara->URL, "mmsc.tele2.ee"); + strcpy(puiPara->IP, "193.12.40.6"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "20416", 5) == 0) + { + //Netherlands T-Mobile + strcpy(sim_info_t->ApnGPRS, "smartsites.t-mobile"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://t-mobilemms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.10.10.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "tmobilemms"); + strcpy(puiPara->PASSWORD, "tmobilemms"); + #endif + } + else if (strncmp(operatorName, "24201", 5) == 0) //norway Telenor + { + strcpy(sim_info_t->ApnGPRS, "telenor.smart"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc"); + strcpy(puiPara->APNMMS, "telenor"); + strcpy(puiPara->IP, "10.10.10.11"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24202", 5) == 0) //norway Telia/Chilli Mobil + { + strcpy(sim_info_t->ApnGPRS, "telia"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mm"); + strcpy(puiPara->APNMMS, "telia"); + strcpy(puiPara->IP, "212.169.66.4"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24205", 5) == 0) //norway Ice Net + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.nwn.no"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "188.149.250.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if ((strncmp(operatorName, "24206", 5) == 0) || (strncmp(operatorName, "24214", 5) == 0)) //norway ice net + { + strcpy(sim_info_t->ApnGPRS, "ice.net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms.ice.net"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "24208", 5) == 0) //norway Get + { + strcpy(sim_info_t->ApnGPRS, "internet.no"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.tdc.dk:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "inetproxy.tdc.dk"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if (strncmp(operatorName, "26801", 5) == 0) //Portugal vodafone + { + strcpy(sim_info_t->ApnGPRS, "net2.vodafone.pt"); + strcpy(sim_info_t->ApnUsername, "vodafone"); + strcpy(sim_info_t->ApnPassword, "vodafone"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.vodafone.pt/servlets/mms"); + strcpy(puiPara->APNMMS, "net2.vodafone.pt"); + strcpy(puiPara->IP, "Iproxy.vodafone.pt"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "vodafone"); + strcpy(puiPara->PASSWORD, "vodafone"); + #endif + } + else if(strncmp(operatorName, "26002", 5) == 0) //Polish Tmobile + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms/servlets/mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.158.194.226"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "26003", 5) == 0) //Polish Orange + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "internet"); + strcpy(sim_info_t->ApnPassword, "internet"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.orange.pl"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.6.104"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + else if(strncmp(operatorName, "26001", 5) == 0) //Polish Plus + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.plusgsm.pl:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "212.2.96.16"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "26006", 5) == 0) //Polish Play + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mmsc.play.pl/mms/wapenc"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.10.25.5"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "30261", 5) == 0) || (strncmp(operatorName, "30269", 5) == 0) || (strncmp(operatorName, "30263", 5) == 0)) //Canada Bell + { + strcpy(sim_info_t->ApnGPRS, "pda.bell.ca"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.bell.ca/mms/wapenc"); + strcpy(puiPara->APNMMS, "pda.bell.ca"); + strcpy(puiPara->IP, "web.wireless.bell.ca"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "30232", 5) == 0) || (strncmp(operatorName, "30272", 5) == 0))//Canada Rogers + { + strcpy(sim_info_t->ApnGPRS, "rogers-core-appl1.apn"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.gprs.rogers.com"); + strcpy(puiPara->APNMMS, "rogers-core-appl1.apn"); + strcpy(puiPara->IP, "10.128.1.69"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "wap@wap"); + strcpy(puiPara->PASSWORD, "wap125"); + #endif + } + /* + else if(strncmp(operatorName, "30222", 5) == 0) //Canada Telus + { + strcpy(sim_info_t->ApnGPRS, "sp.telus.com"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://aliasredirect.net/proxy/mmsc"); + strcpy(puiPara->APNMMS, "sp.telus.com"); + strcpy(puiPara->IP, "74.49.0.18"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + */ + else if((strncmp(operatorName, "30268", 5) == 0) || (strncmp(operatorName, "30278", 5) == 0)) //Canada SaskTel + { + strcpy(sim_info_t->ApnGPRS, "pda.stm.sk.ca"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.sasktel.com"); + strcpy(puiPara->APNMMS, "pda.stm.sk.ca"); + strcpy(puiPara->IP, "mig.sasktel.com"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23002", 5) == 0) //Czech O2 + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.o2active.cz:8002"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "160.218.160.218"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23003", 5) == 0) //Czech Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.11.10.111"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "23001", 5) == 0) //Czech T-mobile + { + strcpy(sim_info_t->ApnGPRS, "internet.t-mobile.cz"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms"); + strcpy(puiPara->APNMMS, "mms.t-mobile.cz"); + strcpy(puiPara->IP, "10.0.0.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28601", 5) == 0) //Turkey Turkcell + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.turkcell.com.tr/servlets/mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "212.252.169.217"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28602", 5) == 0) //Turkey Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "vodafone"); + strcpy(sim_info_t->ApnPassword, "vodafone"); + + #if MMS_SET + strcpy(puiPara->URL, "mms:6001/MM1Servlet"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "217.31.233.18"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "vodafone"); + strcpy(puiPara->PASSWORD, "vodafone"); + #endif + } + else if((strncmp(operatorName, "28603", 5) == 0) ||(strncmp(operatorName, "28604", 5) == 0))//Turkey Avea + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "mms.avea.com.tr/servlets/mms"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "213.161.151.201"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28401", 5) == 0) //Bulgaria A1 + { + strcpy(sim_info_t->ApnGPRS, "internet.a1.bg"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc/"); + strcpy(puiPara->APNMMS, "mms.a1.bg"); + strcpy(puiPara->IP, "10.150.0.33"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28405", 5) == 0) //Bulgaria Telenor + { + strcpy(sim_info_t->ApnGPRS, "telenorbg"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.87.11"); + strcpy(puiPara->PORT, "8004"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "28403", 5) == 0) //Bulgaria VIVACOM + { + strcpy(sim_info_t->ApnGPRS, "internet.vivacom.bg"); + strcpy(sim_info_t->ApnUsername, "VIVACOM"); + strcpy(sim_info_t->ApnPassword, "VIVACOM"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.vivacom.bg"); + strcpy(puiPara->APNMMS, "mms.vivacom.bg"); + strcpy(puiPara->IP, "192.168.123.123"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25503", 5) == 0) //Ukraine KYIVSTAR + { + strcpy(sim_info_t->ApnGPRS, "www.kyivstar.net"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.kyivstar.net"); + strcpy(puiPara->APNMMS, "mms.kyivstar.net"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25501", 5) == 0) //Ukraine Vodafone + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc:8002/"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "192.168.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "25506", 5) == 0) //Ukraine LifeCell + { + strcpy(sim_info_t->ApnGPRS, "internet"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.life"); + strcpy(puiPara->APNMMS, "mms"); + strcpy(puiPara->IP, "10.10.10.10"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21407", 5) == 0) //Spain Movistar + { + strcpy(sim_info_t->ApnGPRS, "telefonica.es"); + strcpy(sim_info_t->ApnUsername, "telefonica"); + strcpy(sim_info_t->ApnPassword, "telefonica"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mms.movistar.es"); + strcpy(puiPara->APNMMS, "telefonica.es"); + strcpy(puiPara->IP, "10.138.255.5"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "21401", 5) == 0) //Spain Vodafone + { + strcpy(sim_info_t->ApnGPRS, "airtelwap.es"); + strcpy(sim_info_t->ApnUsername, "wap@wap"); + strcpy(sim_info_t->ApnPassword, "wap125"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.vodafone.es/servlets/mms"); + strcpy(puiPara->APNMMS, "mms.vodafone.net"); + strcpy(puiPara->IP, "212.73.32.10"); + strcpy(puiPara->PORT, "80"); + strcpy(puiPara->USERNAME, "wap@wap"); + strcpy(puiPara->PASSWORD, "wap125"); + #endif + } + else if(strncmp(operatorName, "21403", 5) == 0) //Spain Simyo + { + strcpy(sim_info_t->ApnGPRS, "orangeworld"); + strcpy(sim_info_t->ApnUsername, "orange"); + strcpy(sim_info_t->ApnPassword, "orange"); + + #if MMS_SET + strcpy(puiPara->URL, "https://mms.orange.es"); + strcpy(puiPara->APNMMS, "orangemms"); + strcpy(puiPara->IP, "172.22.188.25"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if((strncmp(operatorName, "20628", 5) == 0) || (strncmp(operatorName, "20601", 5) == 0) + || (strncmp(operatorName, "52505", 5) == 0) || (strncmp(operatorName, "30222", 5) == 0) + || (strncmp(operatorName, "20809", 5) == 0)) + { + if((strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG91_V)) || (strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG95_V)) \ + || (strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG91_NAXD)) || (strstr(sim_info_t->ModuleVersion, GPRS_MODULE_TYPE_EG95_NAXD))) + { + strcpy(sim_info_t->ApnGPRS, "America.bics"); + } + else + { + strcpy(sim_info_t->ApnGPRS, "bicsapn"); + } + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + } + else if(strncmp(operatorName, "20408", 5) == 0) //kpn sim + { + strcpy(sim_info_t->ApnGPRS, "fast.m2m"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + else if(strncmp(operatorName, "20404", 5) == 0) // wodafeng sim + { + + strcpy(sim_info_t->ApnGPRS, "spe.inet4gd.gdsp"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "\0"); + strcpy(puiPara->APNMMS, "\0"); + strcpy(puiPara->IP, "\0"); + strcpy(puiPara->PORT, "\0"); + strcpy(puiPara->USERNAME, "\0"); + strcpy(puiPara->PASSWORD, "\0"); + #endif + } + /* + else if(strncmp(operatorName, "20601", 5) == 0) //Belgium Proximus + { + strcpy(sim_info_t->ApnGPRS, "internet.proximus.be"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + + #if MMS_SET + strcpy(puiPara->URL, "http://mmsc.proximus.be/mms"); + strcpy(puiPara->APNMMS, "event.proximus.be"); + strcpy(puiPara->IP, "10.55.14.75"); + strcpy(puiPara->PORT, "8080"); + strcpy(puiPara->USERNAME, "mms"); + strcpy(puiPara->PASSWORD, "mms"); + #endif + } + */ + else + { + strcpy(sim_info_t->ApnGPRS, "\0"); + strcpy(sim_info_t->ApnUsername, "\0"); + strcpy(sim_info_t->ApnPassword, "\0"); + return SF_4G_ERROR_AT_APN; + } + + return SF_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/app/sf_app.c b/code/application/source/sf_app/code/source/app/sf_app.c index 0c0581a15..35be902b5 100755 --- a/code/application/source/sf_app/code/source/app/sf_app.c +++ b/code/application/source/sf_app/code/source/app/sf_app.c @@ -6,23 +6,74 @@ */ #include -#include -#include +//#include +//#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//#include "UIInfo/UIInfo.h" +#include + +pthread_mutex_t Param_mutexLock; +pthread_mutex_t GPIO_mutexLock; + + + SINT32 app_ttyusb_IsOpen() +{ + int retryTime = 0; + SINT32 s32ret = 0; + //MLOGD("ttyUSB has not been init, will init ttyUSB!\n"); + while ((s32ret = sf_hal_ttyusb2_init()) < 0) + { + retryTime++; + if((retryTime >=200)&&(retryTime%200 == 0)) + { + //MLOGE("-------ttyUSB init fail!\n"); + s32ret = SF_TTY_ERROR_OPEN; + break; + } + } + + return s32ret; +} int main(int argc, char *argv[]) { + printf("*********************************************\n"); + printf("* *\n"); + printf("* sf_app *\n"); + printf("* *\n"); + printf("*********************************************\n"); //gpio_direction_input(C_GPIO(10)); - sf_mcu_init(); - sf_get_power_on_mode(); - sf_mcu_wdg_set(30); - sf_usb_mux_s(1); - //sf_mcu_reg_set(SF_MCU_CTRL_MODULE_PIR, 1); - //sf_sd_exist_reg_cb(DrvCARD_DetStrgCard); - /*led init*/ - sf_led_init(); - sf_sys_status_led_set(SF_LED_SYS_STATE_PIR_NOT_DETECT); - //sf_battery_thread_init(); + sf_share_mem_file_init(); + sf_com_message_app_init(); + sf_com_message_cardv_init(); + + sf_customer_param_load(); + + SF_MUTEX_INIT_LOCK(Param_mutexLock); + SF_MUTEX_INIT_LOCK(GPIO_mutexLock); + + app_led_group_register(); + //app_message_recv_start(); + + return 0; } diff --git a/code/application/source/sf_app/code/source/app/sf_app.o b/code/application/source/sf_app/code/source/app/sf_app.o deleted file mode 100644 index fa614d8080d4e3f15f5cd150e458b0982748294b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 900 zcmah{T}s115T0#X`=f#u#a~Jl!76r5OQb4-#G>^*f|2?iLMEe_v8{_fdG{a zpdx`f=JB3OgLYc)w%c|GWt}d!Y3=H^i1qptQ1j-JGR{56>T%m2ne1<}f@N{D>U811 z9rmbOUz0j@Yrp9>Q76v-pKeF)7yYj2Q>JeJ7!zU!T^5cIsf-1Pn(%Xp2!TDSK%&qH zyF+<@RBbbE>*DxJXSi|HeOM^B@RS1;z9kzAb>DO_V?Rs_=2ezVA +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_log.h" +#include "sf_ledmng.h" +#include "sf_module.h" +#include "sf_storeMng.h" +#include "sf_keymng.h" +#include "sf_systemMng.h" + +#include "sf_hal_gpio.h" +#include "sf_hal_ttyusb.h" +#include "sf_eg91_server.h" +#include "sf_message_queue.h" +#include "sf_dev_other.h" + +#include "sf_debug.h" +#include "sf_device.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +extern pthread_mutex_t GPIO_mutexLock; + +SF_THREAD_S PirMonitorTskCfg = +{ + .IsRun = 0, + .TskId = -1, +}; + +void* pir_monitoring_thread(void) +{ + SF_MESSAGE_BUF_S stMessageBuf = {0}; + + while(PirMonitorTskCfg.IsRun) + { + if(sf_cap_status_get() == 0) + { + if(!(SF_UPGRADE_ING == sf_upgrade_status_get() || SF_UPGRADE_FAIL == sf_upgrade_status_get())) + sf_hal_gpio_set(SF_HAL_LED_STATUS_G, (sf_dev_pir_status_get()?SF_HAL_LED_STATE_ON:SF_HAL_LED_STATE_OFF)); + } + sf_sleep_ms(50); + } + + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + stMessageBuf.arg2 = LED_GROUP_SIGNAL; + stMessageBuf.arg3 = LED_TYPE_OFF; + sf_com_message_send_to_app(&stMessageBuf); + return NULL; +} +SINT32 app_pir_monitoring_start(void) +{ + SINT32 ret = SF_SUCCESS; + + if(sf_poweron_type_get() != SF_MCU_STARTUP_ONKEY){ + MLOGE("unsupport startup mode !!!\n"); + return SF_FAILURE; + } + if(PirMonitorTskCfg.IsRun) { + MLOGE("thread has already run !!!\n"); + return SF_FAILURE; + } + ret = pthread_create(&PirMonitorTskCfg.TskId, NULL, pir_monitoring_thread, NULL); + if(ret != SF_SUCCESS) + { + SLOGD("thread sf_pir_monitoring_start creat fail!\n"); + return ret; + } + PirMonitorTskCfg.IsRun = 1; + + return SF_SUCCESS; + +} + +SINT32 app_pir_monitoring_stop(void) +{ + SINT32 ret = SF_SUCCESS; + if(!PirMonitorTskCfg.IsRun){ + MLOGE("thread has not run !!!\n"); + return SF_FAILURE; + } + PirMonitorTskCfg.IsRun = 0; + ret = pthread_join(PirMonitorTskCfg.TskId, NULL); + if(ret != SF_SUCCESS) { + MLOGE(" sf_pir_monitoring_stop stop fail!\n"); + return ret; + } + return SF_SUCCESS; +} + +SINT32 app_led_sd_process(SINT32 entype) +{ + switch(entype ) + { + case LED_TYPE_OFF: + sf_hal_gpio_set(SF_HAL_LED_SD_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_SD_R, SF_HAL_LED_STATE_OFF); + break; + case LED_TYPE_RED: + sf_hal_gpio_set(SF_HAL_LED_SD_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_SD_R, SF_HAL_LED_STATE_ON); + break; + case LED_TYPE_YELLOW: + sf_hal_gpio_set(SF_HAL_LED_SD_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_SD_R, SF_HAL_LED_STATE_ON); + break; + case LED_TYPE_GREEN: + sf_hal_gpio_set(SF_HAL_LED_SD_R, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_SD_G, SF_HAL_LED_STATE_ON); + break; + default: + MLOGE("Uknown param [%d]!!!\n",entype); + return SF_FAILURE; + break; + + } + return SF_SUCCESS; +} +SINT32 app_led_status_process(SINT8 entype) +{ + switch(entype ) + { + case LED_TYPE_OFF: + sf_hal_gpio_set(SF_HAL_LED_STATUS_G, SF_HAL_LED_STATE_OFF); + break; + case LED_TYPE_GREEN: + case LED_TYPE_YELLOW: + case LED_TYPE_RED: + case LED_TYPE_ON: + sf_hal_gpio_set(SF_HAL_LED_STATUS_G, SF_HAL_LED_STATE_ON); + break; + default: + MLOGE("Uknown param [%d]!!!\n",entype); + return SF_FAILURE; + break; + } + return SF_SUCCESS; +} +SINT32 app_led_signal_process(SINT8 entype) +{ + switch(entype) + { + case LED_TYPE_OFF: + sf_hal_gpio_set(SF_HAL_LED_SIG1_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_SIG1_R, SF_HAL_LED_STATE_OFF); + break; + case LED_TYPE_RED: + sf_hal_gpio_set(SF_HAL_LED_SIG1_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_SIG1_R, SF_HAL_LED_STATE_ON); + break; + case LED_TYPE_YELLOW: + sf_hal_gpio_set(SF_HAL_LED_SIG1_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_SIG1_R, SF_HAL_LED_STATE_ON); + break; + case LED_TYPE_GREEN: + sf_hal_gpio_set(SF_HAL_LED_SIG1_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_SIG1_R, SF_HAL_LED_STATE_OFF); + break; + default: + MLOGE("Uknown param [%d]!!!\n",entype); + return SF_FAILURE; + break; + + } + return SF_SUCCESS; +} + +SINT32 app_led_bat_process(SINT8 entype) +{ + switch(entype) + { + case LED_TYPE_GREEN: + sf_hal_gpio_set(SF_HAL_LED_BAT_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_BAT_R, SF_HAL_LED_STATE_OFF); + break; + + case LED_TYPE_YELLOW: + sf_hal_gpio_set(SF_HAL_LED_BAT_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_BAT_R, SF_HAL_LED_STATE_ON); + break; + + case LED_TYPE_RED: + sf_hal_gpio_set(SF_HAL_LED_BAT_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_BAT_R, SF_HAL_LED_STATE_ON); + break; + + case LED_TYPE_OFF: + sf_hal_gpio_set(SF_HAL_LED_BAT_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_BAT_R, SF_HAL_LED_STATE_OFF); + break; + default: + MLOGE("Uknown param [%d]!!!\n",entype); + return SF_FAILURE; + break; + } + return SF_SUCCESS; +} +SINT32 app_led_account_process(SINT8 entype) +{ + switch(entype ) + { + case LED_TYPE_OFF: + sf_hal_gpio_set(SF_HAL_LED_USERBIND_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_USERBIND_R, SF_HAL_LED_STATE_OFF); + break; + case LED_TYPE_RED: + sf_hal_gpio_set(SF_HAL_LED_USERBIND_G, SF_HAL_LED_STATE_OFF); + sf_hal_gpio_set(SF_HAL_LED_USERBIND_R, SF_HAL_LED_STATE_ON); + break; + case LED_TYPE_YELLOW: + sf_hal_gpio_set(SF_HAL_LED_USERBIND_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_USERBIND_R, SF_HAL_LED_STATE_ON); + break; + case LED_TYPE_GREEN: + sf_hal_gpio_set(SF_HAL_LED_USERBIND_G, SF_HAL_LED_STATE_ON); + sf_hal_gpio_set(SF_HAL_LED_USERBIND_R, SF_HAL_LED_STATE_OFF); + break; + default: + MLOGE("Uknown param [%d]!!!\n",entype); + return SF_FAILURE; + break; + + } + return SF_SUCCESS; +} +SINT32 app_led_hold_group(SF_LED_GROUD_E enGroupType,SINT32 enstatus) +{ +// MLOGI("enGroupType = %d, enstatus = %d\n",enGroupType, enstatus); + switch(enGroupType) + { + case LED_GROUP_SD: + app_led_sd_process(enstatus); + break; + case LED_GROUP_BAT: + app_led_bat_process(enstatus); + break; + case LED_GROUP_SIGNAL: + app_led_signal_process(enstatus); + break; + case LED_GROUP_ACCOUNT: + app_led_account_process(enstatus); + break; + case LED_GROUP_STATUS: + app_led_status_process(enstatus); + break; + default: + MLOGE("Uknown param [%d]!!!\n",enGroupType); + return SF_FAILURE; + break; + + } + return SF_SUCCESS; +} +SINT32 app_led_all_status_set(SF_LED_STATUS_E enLedStatus,SF_LED_TYPE_E enLedType ) +{ + SINT8 groupID = 0; + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = CMD_LED; + + for(groupID = 0;groupID < LED_GROUP_BUIT;groupID++) { + stMessageBuf.arg1 = enLedStatus; + stMessageBuf.arg2 = groupID; + stMessageBuf.arg3 = enLedType; + sf_com_message_send_to_app(&stMessageBuf); + } + + return SF_SUCCESS; +} +SINT32 app_led_sd_status_return(void) +{ + SF_MESSAGE_BUF_S stMessageBuf = {0}; + + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + switch(sf_sd_status_get()) { + case SF_SD_UNPLUGED: + case SF_SD_OUT: + stMessageBuf.arg3 = LED_TYPE_RED; + break; + case SF_SD_PLUGED: + case SF_SD_OK: + stMessageBuf.arg1 = (sf_customer_param_get()->DebugMode?LED_STATUS_SLOWFLASH_ON:LED_STATUS_HOLD_ON); + stMessageBuf.arg3 = LED_TYPE_GREEN; + break; + case SF_SD_FULL: + case SF_SD_ERROR: + stMessageBuf.arg3 = LED_TYPE_YELLOW; + break; + default: + return SF_FAILURE; + break; + +} + sf_com_message_send_to_app(&stMessageBuf); + return SF_SUCCESS; +} + +SINT32 app_led_net_reg_start(void) +{ + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg1 = LED_STATUS_SLOWFLASH_ON; + stMessageBuf.arg2 = LED_GROUP_SIGNAL; + stMessageBuf.arg3 = LED_TYPE_GREEN; + sf_com_message_send_to_app(&stMessageBuf); + + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg1 = LED_STATUS_SLOWFLASH_ON; + stMessageBuf.arg2 = LED_GROUP_ACCOUNT; + stMessageBuf.arg3 = LED_TYPE_GREEN; + sf_com_message_send_to_app(&stMessageBuf); + + return SF_SUCCESS; +} +SINT32 app_led_net_reg_stop(SINT32 s32ret) +{ + SF_MESSAGE_BUF_S stMessageBuf = {0}; + + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg2 = LED_GROUP_SIGNAL; + if(s32ret == SF_SUCCESS) { + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + UINT8 signalLevel = 0; + sf_4G_signal_level_get(sf_statistics_param_get()->netGeneration,sf_statistics_param_get()->SimSignal,&signalLevel); + MLOGI("signalLevel = %d\n",signalLevel); + switch(signalLevel) + { + case 2: + stMessageBuf.arg3 = LED_TYPE_RED; + break; + case 3: + stMessageBuf.arg3 = LED_TYPE_YELLOW; + break; + case 4: + stMessageBuf.arg3 = LED_TYPE_GREEN; + break; + default: + stMessageBuf.arg3 = LED_TYPE_RED; + break; + } + } + else if(s32ret == SF_4G_ERROR_NO_SIMCARD \ + || s32ret == SF_4G_ERROR_NO_SUPPOET \ + || s32ret == SF_APP_ERROR_NO_SUPPOET) + { + stMessageBuf.arg1 = LED_STATUS_SLOWFLASH_ON; + stMessageBuf.arg3 = LED_TYPE_RED; + } + else if(s32ret == SF_HTTP_ERROR_REQUEST) { + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + stMessageBuf.arg3 = LED_TYPE_RED; + } + else if(s32ret == SF_TTY_ERROR_OPEN) + { + stMessageBuf.arg1 = LED_STATUS_QUICKFLASH_ON; + stMessageBuf.arg3 = LED_TYPE_RED; + } + else { + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + stMessageBuf.arg3 = LED_TYPE_RED; + } + + sf_com_message_send_to_app(&stMessageBuf); + + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg2 = LED_GROUP_ACCOUNT; + if(s32ret == SF_SUCCESS) { + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + stMessageBuf.arg3 = LED_TYPE_GREEN; + } + else { + if(sf_statistics_param_get()->bindFlag) { + if(s32ret == SF_4G_ERROR_NO_SIMCARD \ + || s32ret == SF_4G_ERROR_REG_NET) { + stMessageBuf.arg1 = LED_STATUS_SLOWFLASH_ON; + } + + } + else { + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + } + stMessageBuf.arg3 = LED_TYPE_RED; + } + sf_com_message_send_to_app(&stMessageBuf); + return SF_SUCCESS; +} +SINT32 app_led_poweroff(void) +{ + UINT16 i = 0; + SF_MESSAGE_BUF_S stMessageBuf = {0}; + +// stMessageBuf.cmdId = CMD_LED; +// stMessageBuf.arg1 = LED_STATUS_SLOWFLASH_ON; +// stMessageBuf.arg2 = LED_GROUP_STATUS; +// stMessageBuf.arg3 = LED_TYPE_GREEN; +// sf_com_message_send_to_app(&stMessageBuf); + + while((i < 10)) + { + usleep(500*1000); + i++; + } + if(i == 10) + { + stMessageBuf.arg1 = SF_POWEROFF_KEYON; + stMessageBuf.cmdId = CMD_POWEROFF; + sf_com_message_send_to_app(&stMessageBuf); + } + return SF_SUCCESS; +} + +SINT32 app_led_group_register(void) +{ + + if(sf_poweron_type_get() != SF_MCU_STARTUP_ONKEY && sf_poweron_type_get() != SF_MCU_STARTUP_NORMAL) + return SF_SUCCESS; + + SINT8 i = 0; + SINT8 eventarray[5] = { + LED_GROUP_SD, + LED_GROUP_BAT, + LED_GROUP_SIGNAL, + LED_GROUP_ACCOUNT, + LED_GROUP_STATUS + }; + + sf_led_add_exe(app_led_hold_group); + for (i = 0; i < 5; i++) + { + sf_led_event_register(eventarray[i]); + } + return SF_SUCCESS; +} +SINT32 app_led_pin_init(void) +{ + + if(sf_poweron_type_get() != SF_MCU_STARTUP_ONKEY && sf_poweron_type_get() != SF_MCU_STARTUP_NORMAL) + return SF_SUCCESS; + + sf_hal_gpio_init(SF_HAL_LED_STATUS_G,GPIO_DIR_OUT); + + sf_hal_gpio_init(SF_HAL_LED_SD_G,GPIO_DIR_OUT); + sf_hal_gpio_init(SF_HAL_LED_SD_R,GPIO_DIR_OUT); + + sf_hal_gpio_init(SF_HAL_LED_BAT_G, GPIO_DIR_OUT); + sf_hal_gpio_init(SF_HAL_LED_BAT_R, GPIO_DIR_OUT); + + sf_hal_gpio_init(SF_HAL_LED_SIG1_G,GPIO_DIR_OUT); + sf_hal_gpio_init(SF_HAL_LED_SIG1_R,GPIO_DIR_OUT); + + sf_hal_gpio_init(SF_HAL_LED_USERBIND_G,GPIO_DIR_OUT); + sf_hal_gpio_init(SF_HAL_LED_USERBIND_R,GPIO_DIR_OUT); + + sf_hal_gpio_init(GPIOID_PIR_TEST, GPIO_DIR_IN); +// sf_hal_gpio_init(GPIOID_SIM_INSRET, GPIO_DIR_IN); +// sf_hal_gpio_init(GPIOID_USB_INSERT, GPIO_DIR_IN); + + SINT8 halvalue = 0; + SF_MUTEX_LOCK(GPIO_mutexLock); + sf_hal_gpio_init(SF_KEY_PIN_SYNC,GPIO_DIR_IN); + sf_hal_gpio_get(SF_KEY_PIN_SYNC,&halvalue); + sf_hal_gpio_deinit(SF_KEY_PIN_SYNC); + SF_MUTEX_UNLOCK(GPIO_mutexLock); + MLOGI("halvalue: %d\n",halvalue); + if(halvalue == 0) + return SF_SUCCESS; + + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = CMD_LED; + stMessageBuf.arg1 = LED_STATUS_HOLD_ON; + stMessageBuf.arg2 = LED_GROUP_STATUS; + stMessageBuf.arg3 = LED_TYPE_GREEN; + sf_com_message_send_to_app(&stMessageBuf); + + return SF_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + diff --git a/code/application/source/sf_app/code/source/app/sf_test.c b/code/application/source/sf_app/code/source/app/sf_test.c deleted file mode 100755 index d344b95ac..000000000 --- a/code/application/source/sf_app/code/source/app/sf_test.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * app2.c - * - * Created on: 2023年4月7日 - * Author: NVT02970 - */ - -#include -#include - -int sfmain(int argc, char *argv[]) -{ - //gpio_direction_input(C_GPIO(10)); - - - -} - - - - - - diff --git a/code/application/source/sf_app/code/source/app/sf_test.o b/code/application/source/sf_app/code/source/app/sf_test.o deleted file mode 100644 index 10dc2315508e02983be8c04d9299c0168c741c47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 892 zcmah{T~5M45T0#|{Ai34iN7IeOhhAVX=(u9fG98M1BuUO3q>1+8oDI<LBgF9im(hB$WP9`pw(<%6pD>; z@YEZHAul+#V^iCqwNlwG-B(<<@09K1LY2DIhPo(cKJx+~C+H?Br8+ESlJyix8yRzj zWUUR7Bb(+H*(N*29?2UAdKYnbdc=b7NgRz&bFOOu6AV3#*j&IC&Z3K@17t5P;KTw> z!m5mj$}Hd+_3yYJaoUALhG4*gApnhD2b_6m`6#vz%H#eE2ijwt0rjE?s0dJ5NW0-+ z;17{747pERH@BsTv+g6%dgq!l&PRba#^>hR`V;J8R_sts7Jt)OiQ4bJyrbP!{2&nhi==L(=zJYn^} n +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "sf_log.h" +#include "sf_type.h" +#include "sf_param_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +int sf_msgQueueId = -1; +int cardv_msgQueueId = -1; + + + + +static SINT32 message_queue_send(SINT32 MsgQueueId,SF_MESSAGE_BUF_S *pMessageBuf) +{ + + + size_t msgsz = sizeof(pMessageBuf->cmdId) + sizeof(pMessageBuf->s32Wait) + sizeof(pMessageBuf->arg1) + sizeof(pMessageBuf->arg2)+ sizeof(pMessageBuf->arg3); + if(msgsnd(MsgQueueId, pMessageBuf, msgsz, 0) == -1) + { + return SF_FAILURE; + } + + return SF_SUCCESS; +} +static SINT32 message_queue_recv(SINT32 MsgQueueId,SF_MESSAGE_BUF_S *pMessageBuf) +{ + + size_t msgsz = sizeof(pMessageBuf->cmdId) + sizeof(pMessageBuf->s32Wait) + sizeof(pMessageBuf->arg1) + sizeof(pMessageBuf->arg2)+ sizeof(pMessageBuf->arg3); + + if(msgrcv(MsgQueueId, pMessageBuf, msgsz,0,IPC_NOWAIT) == -1) + { + return SF_FAILURE; + } + + return SF_SUCCESS; +} +static SINT32 message_queue_create(SF_CHAR *pathname,SINT32 *pMsgQueueId) +{ + key_t key; + SF_CHAR touchPath[128] = {0}; + if(access(pathname, F_OK) != 0) + { + sprintf(touchPath, "%s %s","touch",pathname); + system(touchPath); + } + if((key = ftok(pathname,'z')) < 0) + { + MLOGI("ftok error"); + return SF_FAILURE; + } + if ((*pMsgQueueId = msgget(key, IPC_CREAT | 0660)) == -1) + { + MLOGI("MsgQueueId = %#x\n",*pMsgQueueId); + MLOGI("msgget failed errno.%02d is: %s\n", errno, strerror(errno)); + return SF_FAILURE; + } + MLOGI("MsgQueueId = %#x\n",*pMsgQueueId); + return SF_SUCCESS; +} + +SINT32 sf_com_message_app_init(void) +{ + return message_queue_create((char*)"/tmp/sf_message",&sf_msgQueueId); +} +SINT32 sf_com_message_recv_from_app(SF_MESSAGE_BUF_S *pMessageBuf) +{ + return message_queue_recv(sf_msgQueueId,pMessageBuf); +} + +SINT32 sf_com_message_send_to_app(SF_MESSAGE_BUF_S *pMessageBuf) +{ + pMessageBuf->mtype = 1; + return message_queue_send(sf_msgQueueId,pMessageBuf); +} + +SINT32 sf_com_message_cardv_init(void) +{ + return message_queue_create((char*)"/tmp/cardv_message",&cardv_msgQueueId); +} +SINT32 sf_com_message_recv_from_cardv(SF_MESSAGE_BUF_S *pMessageBuf) +{ + return message_queue_recv(cardv_msgQueueId,pMessageBuf); +} + +SINT32 sf_com_message_send_to_cardv(SF_MESSAGE_BUF_S *pMessageBuf) +{ + pMessageBuf->mtype = 1; + return message_queue_send(cardv_msgQueueId,pMessageBuf); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/commMng/sf_share_mem.c b/code/application/source/sf_app/code/source/commMng/sf_share_mem.c new file mode 100755 index 000000000..eeda3b46f --- /dev/null +++ b/code/application/source/sf_app/code/source/commMng/sf_share_mem.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_log.h" +#include "sf_type.h" +#include "sf_param_common.h" +#include "sf_fileMng.h" + +int sf_semId = -1; +int sf_sharMemId = -1; +int sf_sharMemfileId = -1; + +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; +}; + +SINT32 sem_creat(SF_CHAR *pathname,SINT32 *psemid) +{ + SF_CHAR touchPath[128] = {0}; + if(access(pathname, F_OK) != 0) + { + sprintf(touchPath, "%s %s","touch",pathname); + system(touchPath); + } + key_t key = ftok(pathname, 111); + if(key < 0) + { + perror("ftok"); + return SF_FAILURE; + } + + *psemid = semget(key, 1, IPC_CREAT|IPC_EXCL|0666); + if(*psemid < 0) + { + perror("semget"); + return SF_FAILURE; + } + + union semun un; + un.val = 1; + if(semctl(*psemid, 0, SETVAL, un)<0) + { + perror("semctl"); + return SF_FAILURE; + } + return SF_SUCCESS; + +} +SINT32 sem_check(SINT32 semid, SINT32 who, SINT32 op) +{ + + struct sembuf sf; + sf.sem_num = who; + sf.sem_op = op; + sf.sem_flg = 0; + + if(semop(semid, &sf, 1) < 0) + { + perror("semop"); + return SF_FAILURE; + } + return SF_SUCCESS; +} + +SINT32 sf_sem_init(SF_CHAR *pathname,SINT32 *psemid) +{ + return sem_creat(pathname,psemid); +} + +SINT32 sf_sem_down(SINT32 semid, SINT32 who) +{ + return sem_check(semid, who, -1); +} + +SINT32 sf_sem_up(SINT32 semid, SINT32 who) +{ + return sem_check(semid, who, 1); +} +SINT32 sf_sem_deinit(SINT32 semid) +{ + if(semctl(semid, 0, IPC_RMID) < 0) + { + perror("semctl"); + return SF_FAILURE; + } + return SF_SUCCESS; +} +int share_mem_create(SF_CHAR *pathname,int size,SINT32 *pshmID) +{ + SF_CHAR touchPath[128] = {0}; + if(access(pathname, F_OK) != 0) + { + sprintf(touchPath, "%s %s","touch",pathname); + system(touchPath); + } + key_t key = ftok(pathname, 111); + if(key < 0) + { + perror("ftok"); + return SF_FAILURE; + } + + *pshmID = shmget(key, size, IPC_CREAT|0666); + if(*pshmID == -1) + { + perror("shmget"); + return SF_FAILURE; + } + + return SF_SUCCESS; +} + +int share_mem_destory(int shmID) +{ + + if(shmctl(shmID, IPC_RMID, NULL) < 0 ) + { + perror("shmctl"); + return SF_FAILURE; + } + + return SF_SUCCESS; +} +void* share_mem_get(int shmID) +{ + return shmat(shmID, NULL, 0); +} +SINT32 sf_share_mem_init(SF_CHAR *pathname,int size,SINT32 *pshmID) +{ + return share_mem_create(pathname,size,pshmID); +} +SINT32 sf_share_mem_deinit(SINT32 shmID) +{ + return share_mem_destory(shmID); +} +void* sf_share_mem_get(int shmID) +{ + return share_mem_get(shmID); +} + +SINT32 sf_share_mem_file_init(void) +{ + SF_SRCFILE_ATTR_S *pThumbFileCfg = 0; + if(SF_SUCCESS == sf_share_mem_init((char*)"/tmp/sf_file",sizeof(SF_SRCFILE_ATTR_S),&sf_sharMemfileId)) + { + pThumbFileCfg = (SF_SRCFILE_ATTR_S *)sf_share_mem_get(sf_sharMemfileId); + if(pThumbFileCfg <= 0) + { + MLOGI("creat share mem failed!!!\n"); + return SF_FAILURE; + } + else + { + sf_file_thumb_cfg_set(pThumbFileCfg); + MLOGI("creat share mem succeed!!!\n"); + return SF_SUCCESS; + } + } + return SF_FAILURE; +} +SINT32 sf_share_mem_customer_init(void) +{ + SF_PDT_PARAM_CFG_S *pSfCustomerPara = 0; + if(SF_SUCCESS == sf_share_mem_init((char*)"/tmp/sf_share",sizeof(SF_PDT_PARAM_CFG_S),&sf_sharMemId)) + { + pSfCustomerPara = (SF_PDT_PARAM_CFG_S *)sf_share_mem_get(sf_sharMemId); + if(pSfCustomerPara <= 0) + { + MLOGI("creat share mem failed!!!\n"); + return SF_FAILURE; + } + else + { + sf_customer_param_set(pSfCustomerPara); + MLOGI("creat share mem succeed!!!\n"); + return SF_SUCCESS; + } + + } + return SF_FAILURE; + +} +SINT32 sf_share_mem_file_deinit(void) +{ + return sf_share_mem_deinit(sf_sharMemfileId); +} + +SINT32 sf_share_mem_customer_deinit(void) +{ + return sf_share_mem_deinit(sf_sharMemId); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/dataMng/sf_dataMng.c b/code/application/source/sf_app/code/source/dataMng/sf_dataMng.c new file mode 100755 index 000000000..bf149373d --- /dev/null +++ b/code/application/source/sf_app/code/source/dataMng/sf_dataMng.c @@ -0,0 +1,352 @@ +#include +#include +#include +#include +#include +#include +#include +#if defined(CFG_TRANSDATA_AT) +#include "sf_transdata1.h" +#endif +#include "sf_dataMng.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +SF_PARA_TIME_S rtcTime = {0}; +SF_CMD_QUERYPENDING_E PendingOrder = SF_QUERYPENDING_COMMAND_BUTT; +UINT8 CanUpload = 0; +UINT8 UploadMode = 0; +UINT8 HasCommand = 0; +UINT16 SubscribeRet = 0; + + +static UINT8 auchCRCHi[256] = { +0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, + 0xC0, 0x80, 0x41, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, + 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x00, 0xC1, + 0x81, 0x40, 0x01, 0xC0, 0x80, + 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x00, 0xC1, + 0x81, 0x40, 0x01, 0xC0, 0x80, + 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x01, 0xC0, 0x80, + 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x00, 0xC1, + 0x81, 0x40, 0x01, 0xC0, 0x80, + 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, + 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40 }; + +static UINT8 auchCRCLo[256] = { +0x00, 0xC0, 0xC1, + 0x01, 0xC3, 0x03, 0x02, 0xC2, + 0xC6, 0x06, 0x07, 0xC7, 0x05, + 0xC5, 0xC4, 0x04, 0xCC, 0x0C, + 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, + 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, + 0xC9, 0x09, 0x08, 0xC8, 0xD8, + 0x18, 0x19, 0xD9, 0x1B, 0xDB, + 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, + 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, + 0x17, 0x16, 0xD6, 0xD2, 0x12, + 0x13, 0xD3, 0x11, 0xD1, 0xD0, + 0x10, 0xF0, 0x30, 0x31, 0xF1, + 0x33, 0xF3, 0xF2, 0x32, 0x36, + 0xF6, 0xF7, 0x37, 0xF5, 0x35, + 0x34, 0xF4, 0x3C, 0xFC, 0xFD, + 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, + 0xFA, 0x3A, 0x3B, 0xFB, 0x39, + 0xF9, 0xF8, 0x38, 0x28, 0xE8, + 0xE9, 0x29, 0xEB, 0x2B, 0x2A, + 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, + 0x2D, 0xED, 0xEC, 0x2C, 0xE4, + 0x24, 0x25, 0xE5, 0x27, 0xE7, + 0xE6, 0x26, 0x22, 0xE2, 0xE3, + 0x23, 0xE1, 0x21, 0x20, 0xE0, + 0xA0, 0x60, 0x61, 0xA1, 0x63, + 0xA3, 0xA2, 0x62, 0x66, 0xA6, + 0xA7, 0x67, 0xA5, 0x65, 0x64, + 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, + 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, + 0x6A, 0x6B, 0xAB, 0x69, 0xA9, + 0xA8, 0x68, 0x78, 0xB8, 0xB9, + 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, + 0xBD, 0xBC, 0x7C, 0xB4, 0x74, + 0x75, 0xB5, 0x77, 0xB7, 0xB6, + 0x76, 0x72, 0xB2, 0xB3, 0x73, + 0xB1, 0x71, 0x70, 0xB0, 0x50, + 0x90, 0x91, 0x51, 0x93, 0x53, + 0x52, 0x92, 0x96, 0x56, 0x57, + 0x97, 0x55, 0x95, 0x94, 0x54, + 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, + 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, + 0x9B, 0x5B, 0x99, 0x59, 0x58, + 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, + 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, + 0x4C, 0x8C, 0x44, 0x84, 0x85, + 0x45, 0x87, 0x47, 0x46, 0x86, + 0x82, 0x42, 0x43, 0x83, 0x41, + 0x81, 0x80, 0x40 }; + + + + UINT16 crcCheck( UINT8 strContent[],UINT16 usDataLen,UINT16 crc) +{ + UINT16 uIndex; + + UINT8 uchCRCHi = 0xFF; + UINT8 uchCRCLo = 0xFF; + UINT16 i = 0; + UINT16 value=0; + + for (i = 0; i < usDataLen; i++) { + uIndex = (uchCRCHi ^ strContent[i]) & 0xff; + + uchCRCHi = (uchCRCLo ^ auchCRCHi[uIndex]); + uchCRCLo = auchCRCLo[uIndex]; + } + + value = ((((UINT16) uchCRCHi) << 8 | (((UINT16) uchCRCLo) & 0xff))) & 0xffff; + + if (crc == value) { + return 0; + } else { + return 1; + } + +} + +UINT16 makeCrc(UINT8 strContent[], UINT16 len) +{ + UINT16 uIndex; + UINT16 usDataLen = len; + + UINT8 uchCRCHi = 0xFF; + UINT8 uchCRCLo = 0xFF; + UINT16 value=0; + UINT16 i = 0; + for (i = 0; i < usDataLen; i++) { + uIndex = (uchCRCHi ^ strContent[i]) & 0xff; + + uchCRCHi = (uchCRCLo ^ auchCRCHi[uIndex]); + uchCRCLo = auchCRCLo[uIndex]; + } + value = ((((UINT16) uchCRCHi) << 8 | (((UINT16) uchCRCLo) & 0xff))) & 0xffff; + return value; +} + +void sf_data_subscribe_result_set(UINT16 ret) +{ + if(ret == SF_SUCCESS) + SubscribeRet = 0; +// else if(ret == SF_TCP_ERROR_SUBSCRIBE_NO_FILE) +// SubscribeRet = 2; + else + SubscribeRet = 1; +} + +SF_PARA_TIME_S* sf_server_time_get(void) +{ + return &rtcTime; +} + + +UINT8 sf_data_has_command_get(void) +{ + return HasCommand; +} +UINT8 sf_data_transfer_mode_get(void) +{ + return UploadMode; +} +SINT32 sf_data_cam_local_time_get(SF_PARA_TIME_S* pstdata) +{ + memcpy(pstdata,&rtcTime,sizeof(SF_PARA_TIME_S)); + return SF_SUCCESS; +} +UINT32 sf_data_pendingcmd_get(void) +{ + return PendingOrder; +} +SINT32 sf_data_grouping_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_login(pstdata,pfnParam); + #else + return sf_net_packetgrouping_login(pstdata,pfnParam); + #endif +} +SINT32 sf_data_grouping_fileresult(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam,SF_VOID *pstfileAttr) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_fileresult(pstdata,(SF_PDT_PARAM_CFG_S*)pfnParam->pstParam,pstfileAttr); + #else + return sf_net_packetgrouping_fileresult(pstdata,(SF_PDT_PARAM_STATISTICS_S*)pfnParam->pstaticParam,(SF_REPORT_FILE_ATTR_S*)pstfileAttr); + #endif +} +SINT32 sf_data_grouping_disconnection(SF_DATA_ATTR_S *pstdata,SF_VOID *Param) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_disconnection(pstdata,Param); + #else + //acm http need tcp alive + return sf_net_packetgrouping_disconnection(pstdata,Param); + #endif +} +SINT32 sf_data_grouping_query_cmd(SF_DATA_ATTR_S *pstdata) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_query_cmd(pstdata); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_grouping_query_cmd_param(SF_DATA_ATTR_S *pstdata) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_query_cmd_param(pstdata); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_grouping_cmd_report(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam, SF_FILE_ATTR_S *pstfileAttr) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_cmd_report(pstdata,pfnParam,pstfileAttr); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_grouping_get_bind_account(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetgrouping_get_bind_account(pstdata,pfnParam); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_grouping_sync_cfg(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return SF_SUCCESS; + #else + return sf_net_packetgrouping_sync(pstdata,pfnParam); + #endif +} + +SINT32 sf_data_analysis_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_login(pstdata,pfnParam); + #else + return sf_net_packetanalysis_login(pstdata,pfnParam); + #endif +} +SINT32 sf_data_analysis_fileresult(SF_DATA_ATTR_S *pstdata) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_fileresult(pstdata); + #else + return sf_net_packetanalysis_fileresult(pstdata); + #endif +} +SINT32 sf_data_analysis_query_cmd(SF_DATA_ATTR_S *pstdata) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_query_cmd(pstdata); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_analysis_query_cmd_param(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_query_cmd_param(pstdata,pfnParam); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_analysis_cmd_report(SF_DATA_ATTR_S *pstdata) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_cmd_report(pstdata); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_analysis_bind_account(SF_DATA_ATTR_S *pstdata,SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_bind_account(pstdata,pfnParam); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_analysis_trigger(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return sf_packetanalysis_trigger(pstdata,pfnParam); + #else + return SF_SUCCESS; + #endif +} +SINT32 sf_data_analysis_sync_cfg(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + #if defined(CFG_TRANSDATA_AT) + return SF_SUCCESS; + #else + return sf_net_packetanalysis_sync(pstdata,pfnParam); + #endif +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + diff --git a/code/application/source/sf_app/code/source/dataMng/sf_datahttp.c b/code/application/source/sf_app/code/source/dataMng/sf_datahttp.c new file mode 100755 index 000000000..af1dc57bd --- /dev/null +++ b/code/application/source/sf_app/code/source/dataMng/sf_datahttp.c @@ -0,0 +1,1403 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "sf_type.h" +#include "sf_log.h" + +#include "cJSON.h" +#include "sf_module.h" + +#include "sf_storeMng.h" +#include "sf_dev_other.h" + +#include "sf_systemMng.h" +#include "sf_dataMng.h" +#include "sf_commu_mcu_reg.h" +#include "sf_datahttp.h" +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +extern UINT8 UploadMode; +extern SF_PARA_TIME_S rtcTime; + + LOGIN_ACM_RESPONSE_S stLoginAcmResponse = { 0 };//login_acm_response + + SF_REPORT_FILE_ATTR_S stSubReportFileAttr = { 0 }; + SF_REPORT_FILE_ATTR_S stThmReportFileAttr = { 0 }; + + + static SINT32 packet_log_printf(UINT8 *pbuf,UINT16 lenth) +{ + UINT16 i= 0; + for(i = 0;i < lenth;i++) + { + if(i%5 == 0) + printf("[%02d,%02d] = {",i,((lenth - i) < 5)?(lenth-1):(i+4)); + + if((i+1)%5 == 0 || (i+1) == lenth) + printf("0x%02x}\n",*pbuf++); + else + printf("0x%02x,",*pbuf++); + } + return SF_SUCCESS; + +} + static SINT32 packet_gps_parse(char *pstring,SF_PDT_PARAM_STATISTICS_S *pStaticParam) +{ + *pstring++ = pStaticParam->Latitude[9]; + *pstring++ = pStaticParam->Latitude[0]; + *pstring++ = pStaticParam->Latitude[1]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Latitude[2]; + *pstring++ = pStaticParam->Latitude[3]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Latitude[5]; + *pstring++ = pStaticParam->Latitude[6]; + *pstring++ = '-'; + + *pstring++ = pStaticParam->Longitude[10]; + *pstring++ = pStaticParam->Longitude[0]; + *pstring++ = pStaticParam->Longitude[1]; + *pstring++ = pStaticParam->Longitude[2]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Longitude[3]; + *pstring++ = pStaticParam->Longitude[4]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Longitude[6]; + *pstring++ = pStaticParam->Longitude[7]; + *pstring++ = '\0'; + +// *pstring++ = 'N'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '-'; + +// *pstring++ = 'E'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '\0'; + return SF_SUCCESS; +} + static SINT32 debug_remotecontrol_packet( SF_PDT_PARAM_CFG_S *pstparam) + { + if(pstparam->GprsMode == 0) + { + pstparam->DailyReportswitch = 0; + pstparam->DailyReportTime.Hour = 24; + pstparam->DailyReportTime.Min = 0; + } + else if(pstparam->GprsMode == 1) + { + pstparam->DailyReportswitch = 0; + pstparam->DailyReportTime.Hour = 0; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 2) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 0; + pstparam->DailyReportTime.Min = 30; + + } + else if(pstparam->GprsMode == 3) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 1; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 4) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 2; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 5) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 3; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 6) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 4; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 7) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 6; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 8) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 12; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 9) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 24; + pstparam->DailyReportTime.Min = 0; + + } + return SF_SUCCESS; + } + + LOGIN_ACM_RESPONSE_S* sf_get_login_reponse(void) + { + return &stLoginAcmResponse; + } + + SF_REPORT_FILE_ATTR_S* sf_get_sub_report_file_attr(void) + { + return &stSubReportFileAttr; + } + + SF_REPORT_FILE_ATTR_S* sf_get_thm_report_file_attr(void) + { + return &stThmReportFileAttr; + } + + static SINT32 data_error_collection(UINT32 valueint) + { + switch(valueint) + { + case SF_SYS_ERR: + SLOGE("SF_SYS_ERR\n"); + break; + case SF_PARA_ERR: + SLOGE("SF_PARA_ERR\n"); + break; + case SF_DEV_NOT_EXIST: + SLOGE("SF_DEV_NOT_EXIST\n"); + break; + case SF_USER_NOT_EXIST: + SLOGE("SF_USER_NOT_EXIST\n"); + break; + case SF_SIM_NOT_EXIST: + SLOGE("SF_SIM_NOT_EXIST\n"); + break; + case SF_SIM_NET_NOT_TURN_ON: + SLOGE("SF_SIM_NET_NOT_TURN_ON\n"); + break; + case SF_SIM_DEV_NOT_BIND: + SLOGE("SF_SIM_DEV_NOT_BIND\n"); + break; + default: + SLOGE("undefined error\n!!!"); + break; + } + return SF_SUCCESS; +} + + int sf_http_decrypt(char* src, char* dst, int len) + { + #define MBEDTLS_CIPHER_AES_128_CBC 5 + #define MBEDTLS_DECRYPT 0 + + char buf[256] = {0}; + UINT8 datalen = 0; + + datalen = sf_base64_decode(src, buf); + + datalen = sf_cipher(MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_DECRYPT, (UINT8 *)buf, (UINT8 *)dst, datalen); + + return datalen; + + } + + static SINT32 http_response_status_code(char *data) + { + char *p = NULL; + char ack[3] = {0}; + + p = strstr(data, "HTTP/1.1"); + memcpy(ack, p+9, 3); + switch(atoi(ack)/100) + { + case 1: + MLOGI(">>>information corresponding\n"); + return SF_SUCCESS; + + case 2: + MLOGI(">>>successful response\n"); + return SF_SUCCESS; + + case 3: + MLOGI(">>>redirect message\n"); + return SF_SUCCESS; + + case 4: + MLOGE(">>>Client error response\n"); + return SF_FAILURE; + + case 5: + MLOGE(">>>server error response\n"); + return SF_FAILURE; + + default: + MLOGE(">>>undefined error response\n"); + return SF_FAILURE; + + } + + return SF_SUCCESS; + } + + int isleap(int year) + { + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); + } + + int get_yeardays(int year) + { + if (isleap(year)) + return 366; + return 365; + } + + + void split_year_day_std(int days, int *year, int *day) + { + int curr_day = get_yeardays(*year=1970); + while (days >= curr_day) + { + days -= curr_day; + *year += 1; + curr_day = get_yeardays(*year); + } + *day = days; + } + void get_subtime(int sec_in_day, SF_PARA_TIME_S *tmx) + { + tmx->Hour = sec_in_day/(60*60); + tmx->Min = sec_in_day%(60*60)/60; + tmx->Sec = sec_in_day%60; + } + void get_monthday(int day, int is_leap, SF_PARA_TIME_S *tmx) + { + int i, mons[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if (is_leap) mons[1] += 1; + for (i = 0; i < 12; ++i) + { + if (day < mons[i]) + { + tmx->Mon = i+1; + tmx->Day = day+1; + return; + } + day -= mons[i]; + } + } + + void sf_get_date(UINT32 second, SF_PARA_TIME_S *ptmx) + { + SF_PARA_TIME_S tmx; + + split_year_day_std(second/86400, (int*)&tmx.Year, (int*)&tmx.Day); + get_monthday(tmx.Day, isleap(tmx.Year), &tmx); + get_subtime(second%86400,&tmx); + + printf("-----After------%04d/%02d/%02d %02d:%02d:%02d-------------------------------------\n", + tmx.Year, tmx.Mon, tmx.Day, tmx.Hour, tmx.Min, tmx.Sec); + ptmx->Year = tmx.Year; + ptmx->Mon = tmx.Mon; + ptmx->Day = tmx.Day; + ptmx->Hour = tmx.Hour; + ptmx->Min = tmx.Min; + ptmx->Sec = tmx.Sec; + + } + + + UINT32 sf_get_seconds(SF_PARA_TIME_S rtc) + { + UINT32 res = 0; + + UINT32 tempYear = rtc.Year; + UINT32 tempMon = rtc.Mon; + UINT32 tempDay = rtc.Day; + UINT32 tempHour = rtc.Hour; + UINT32 tempMin = rtc.Min; + UINT32 tempSec = rtc.Sec; + + + if(tempMon <= 2) + { + tempMon += 10; + tempYear -= 1; + } + else + { + tempMon -=2; + } + + /*printf("----32 gprs_getSeconds---------%d/%d/%d %d:%d%d---------------------------------------\n", rtc.tmx_Year, rtc.tmx_mon, rtc.tmx_mday, rtc.tmx_hour, rtc.tmx_min, rtc.tmx_sec);*/ + + res = (UINT32)(tempYear/4 -tempYear/100 + tempYear/400) + 367*tempMon/12 + tempDay + tempYear * 365 -719499; + + /*printf("----32 gprs_getSeconds---------res:%x----------%ld-----------------------------\n", res, res);*/ + + res = ((res*24 + tempHour) * 60 + tempMin)*60 + tempSec; + + /*printf("-64 ---gprs_getSeconds---------res:%x----------%ld-----------------------------\n", res, res);*/ + return res; + + } + + SINT32 sf_net_packetgrouping_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) + +{ + UINT8 signalLevel = 0; + SF_CHAR mcuVer[16]={0}; + SF_CHAR ver[24] = { 0 }; + cJSON *usr ; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + SF_STORE_ATTR_S storeattrs; + sf_sd_info_get(&storeattrs); + if(storeattrs.SDStatus != 0) + { + storeattrs.SDTotalSize = 0; + storeattrs.SDFree = 0; + } + memset(pstdata->databuf, '\0', sizeof(pstdata->databuf)); + sf_sys_software_version_get(ver); + sprintf(mcuVer, "%d.%d.%d", (sf_get_mcu_ver() & 0xff00) >> 8, sf_get_mcu_ver() & 0x00ff, sf_get_mcu_sub_ver()); + + sf_4G_signal_level_get(pStaticParam->netGeneration,pStaticParam->SimSignal,&signalLevel); + if(signalLevel == 4) + signalLevel = 31; + else if(signalLevel == 3) + signalLevel = 13; + else if(signalLevel == 2) + signalLevel = 7; + + usr=cJSON_CreateObject(); + + cJSON_AddStringToObject(usr, "imei", pStaticParam->IMEI); + cJSON_AddStringToObject(usr, "iccid", pStaticParam->SimID); + cJSON_AddNumberToObject(usr, "loginType", sf_poweron_type_get()); + cJSON_AddStringToObject(usr, "sfVersion", ver); + cJSON_AddStringToObject(usr, "fwVersion", pStaticParam->ModuleSubversion); + cJSON_AddStringToObject(usr, "mcuVersion", mcuVer); + cJSON_AddStringToObject(usr, "carriers", pStaticParam->ServiceProvider); + + cJSON_AddNumberToObject(usr, "sdcapacity", storeattrs.SDTotalSize); + cJSON_AddNumberToObject(usr, "sdfree", storeattrs.SDFree); + cJSON_AddNumberToObject(usr, "sdPic", pStaticParam->SdTotalFile); + + cJSON_AddNumberToObject(usr, "signalStrength", signalLevel); + cJSON_AddNumberToObject(usr, "fahrenheit", pStaticParam->FcTemper-22); + cJSON_AddNumberToObject(usr, "battery", pStaticParam->BatRemainCap); + + char *out = cJSON_Print(usr); + + sprintf((char*)pstdata->databuf, "POST /AcmService/acmhttp/v1/devLogin" + " HTTP/1.1\r\n" + "Host:%s\r\n" + "Connection: keep-alive\r\n" + "Content-Length: %d\r\n" + "Content-Type: application/json\r\n\r\n" + "%s",pStaticParam->AcmIP,strlen(out),out); + free(out); + cJSON_Delete(usr); + pstdata->dataSize = strlen((const char*)pstdata->databuf); + #ifndef SF_VERSION_RELEASE + MLOGD("send_buff:%d byte\n***********************\n%s\n", pstdata->dataSize, pstdata->databuf); + #endif + return SF_SUCCESS; + + } + + SINT32 sf_net_packetgrouping_fileresult(SF_DATA_ATTR_S *pstdata, SF_PDT_PARAM_STATISTICS_S *pStaticParam,SF_REPORT_FILE_ATTR_S *pstfileAttr) + { + SINT32 ret = 0; + //SINT32 totalFileNum = 0; + //UINT32 pSDFree= 0, pSDTotalSize = 0; + // SINT32 fahrenheit = 0; + //UINT8 loginType = 1; + SF_CHAR ver[24] = { 0 }; + SINT16 i = 0; + char *msg = NULL; + memset(pstdata->databuf, '\0', sizeof(pstdata->databuf)); + cJSON *jsonArray = cJSON_CreateArray(); + for(i = 0; i < pstfileAttr->filecnt; i++) + { + cJSON *ArrayItem0 = cJSON_CreateObject(); + cJSON_AddStringToObject(ArrayItem0,"imei", pStaticParam->IMEI); + cJSON_AddNumberToObject(ArrayItem0,"uploadType", 2); + cJSON_AddNumberToObject(ArrayItem0,"type", pstfileAttr->stSendFileAttr[i].enFileTye); + cJSON_AddNumberToObject(ArrayItem0,"fileSize", pstfileAttr->stSendFileAttr[i].SendFileSize); + cJSON_AddStringToObject(ArrayItem0,"data", pstfileAttr->stSendFileAttr[i].SendFileName); + cJSON_AddStringToObject(ArrayItem0,"bindFile", pstfileAttr->stSendFileAttr[i].SubFileName); + cJSON_AddNumberToObject(ArrayItem0,"code", pstfileAttr->stSendFileAttr[i].SendRet); + cJSON_AddNumberToObject(ArrayItem0,"did", pStaticParam->Did); + + //cJSON_AddNumberToObject(ArrayItem0, "dayNight", 1); + //cJSON_AddNumberToObject(ArrayItem0, "fahrenheit", fahrenheit); + //cJSON_AddNumberToObject(ArrayItem0, "phases", 1); + //cJSON_AddNumberToObject(ArrayItem0, "loginType", loginType); + + cJSON_AddItemToArray(jsonArray,ArrayItem0); + } + +// cJSON *root = cJSON_CreateObject(); + sf_sys_software_version_get(ver); +// cJSON_AddStringToObject(root, "sfVersion", ver); +// cJSON_AddItemToObject( root, "fileResultDTOList", jsonArray); +// + msg = cJSON_Print(jsonArray); + cJSON_Delete(jsonArray); + + SF_STORE_ATTR_S storeattrs; + sf_sd_info_get(&storeattrs); + if(storeattrs.SDStatus != 0) + { + storeattrs.SDTotalSize = 0; + storeattrs.SDFree = 0; + } + + sprintf((char*)pstdata->databuf, "POST /AcmService/acmhttp/v1/fileResultReport?" + "sdcapacity=%d" + "&sdfree=%d" + "&sdPic=%d" + "&fahrenheit=%d" + "&sfVersion=%s" + "&signalStrength=%d" + "&battery=%d" + " HTTP/1.1\r\n" + "Host:%s\r\n" + "token:%s\r\n" + "Connection: keep-alive\r\n" + "Content-Length: %d\r\n" + "Content-Type: application/json\r\n\r\n" + "%s", + storeattrs.SDTotalSize,\ + storeattrs.SDFree, \ + pStaticParam->SdTotalFile, \ + pStaticParam->FcTemper-22, \ + ver, \ + pStaticParam->SimSignal, \ + pStaticParam->BatRemainCap,\ + pStaticParam->AcmIP,\ + pStaticParam->Token,\ + strlen(msg),\ + msg); + free(msg); + pstdata->dataSize = strlen((const char *)pstdata->databuf); + #ifndef SF_VERSION_RELEASE + MLOGD("send_buff:%d byte\n***********************\n%s\n", pstdata->dataSize, pstdata->databuf); + #endif + return ret; + } + SINT32 sf_net_packetgrouping_sync(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) + { + //UINT16 param = 0; + SF_CHAR time[16] = {0}; + //SF_CHAR workTimerWeekStr[10] = {0}; + //SF_CHAR gpsStr[32] = {0}; + cJSON *root = NULL; + + memset(pstdata->databuf, '\0', sizeof(pstdata->databuf)); + SF_PDT_PARAM_CFG_S *pstparam = pfnParam->pstParam; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + root = cJSON_CreateObject(); + + cJSON_AddNumberToObject(root, "did", pStaticParam->Did); + cJSON_AddNumberToObject(root, "batteryType", pstparam->BatteryType); + cJSON_AddNumberToObject(root, "video", pstparam->CamMode+1); + cJSON_AddNumberToObject(root, "ledNumber", pstparam->FlashLed); + cJSON_AddNumberToObject(root, "sdcycleFlag", pstparam->SdLoop); + cJSON_AddNumberToObject(root, "pirswitch", pstparam->PirSwitch); + cJSON_AddNumberToObject(root, "stamp", pstparam->StampSwitch); + cJSON_AddNumberToObject(root, "image", pstparam->ImgSize); + cJSON_AddNumberToObject(root, "multishot", pstparam->Multishot); + cJSON_AddNumberToObject(root, "sdFormat", sf_get_login_reponse()->sdFormatCommand); + cJSON_AddNumberToObject(root, "devResetCommand", sf_get_login_reponse()->devResetCommand); + + /*0:1080P, 1:720P, 2:480P*/ + cJSON_AddNumberToObject(root, "videoSize", pstparam->VideoSize+1); + if(pstparam->VideoSize == SF_VIDEO_SIZE_1080) + pstparam->VideoLenth = 10; + else if(pstparam->VideoSize == SF_VIDEO_SIZE_720) + pstparam->VideoLenth = 20; + else if(pstparam->VideoSize == SF_VIDEO_SIZE_WVGA) + pstparam->VideoLenth = 30; + + cJSON_AddNumberToObject(root, "videoLength", pstparam->VideoLenth); + cJSON_AddNumberToObject(root, "pirsentivity", pstparam->DigitPirSensitivity); + + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "delayFlag", pstparam->PirDelaySwitch); + sprintf(time, "%02d%02d%02d", pstparam->PirDelayTime.Hour, pstparam->PirDelayTime.Min, pstparam->PirDelayTime.Sec); + cJSON_AddStringToObject(root, "delayValue", time); + + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "timelapseFlag", pstparam->TimelapseSwitch); + sprintf(time, "%02d%02d%02d", pstparam->TimelapseTime.Hour, pstparam->TimelapseTime.Min, pstparam->TimelapseTime.Sec); + cJSON_AddStringToObject(root, "timelapseValue", time); + + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "timerFlag", pstparam->WorkTime1Switch); + sprintf(time, "%02d%02d-%02d%02d", pstparam->WorkTime[0].StartTime.Hour, pstparam->WorkTime[0].StartTime.Min, pstparam->WorkTime[0].StopTime.Hour, pstparam->WorkTime[0].StopTime.Min); + cJSON_AddStringToObject(root, "timerValue", time); + + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "timerFlag2", pstparam->WorkTime2Switch); + sprintf(time, "%02d%02d-%02d%02d", pstparam->WorkTime[1].StartTime.Hour, pstparam->WorkTime[1].StartTime.Min, pstparam->WorkTime[1].StopTime.Hour, pstparam->WorkTime[1].StopTime.Min); + cJSON_AddStringToObject(root, "timerValue2", time); + + #if 1 + debug_remotecontrol_packet(pstparam); + #endif + char stringGPS[21] = {0}; + packet_gps_parse(stringGPS,pStaticParam); + cJSON_AddNumberToObject(root, "gpsFlag", pstparam->GPSFlag); + cJSON_AddStringToObject(root, "gps", stringGPS); + + cJSON_AddNumberToObject(root, "smsctrl", pstparam->GprsMode); + + memset(time, 0, sizeof(time)); + cJSON_AddNumberToObject(root, "dailyreportFlag", pstparam->DailyReportswitch); + sprintf(time, "%02d%02d", pstparam->DailyReportTime.Hour, pstparam->DailyReportTime.Min); + cJSON_AddStringToObject(root, "dailyreportValue", time); + + char *devparam = cJSON_Print(root); + + sprintf((char*)pstdata->databuf, "POST /AcmService/acmhttp/v1/syncConfig?modifyFlag=%d" + " HTTP/1.1\r\n" + "Host:%s\r\n" + "token:%s\r\n" + "Connection: keep-alive\r\n" + "Content-Length: %d\r\n" + "Content-Type: application/json\r\n\r\n" + "%s", + pstparam->ParaSync, \ + pStaticParam->AcmIP,\ + pStaticParam->Token,\ + strlen(devparam),\ + devparam); + + + free(devparam); + cJSON_Delete(root); + pstdata->dataSize = strlen((const char *)pstdata->databuf); + #ifndef SF_VERSION_RELEASE + MLOGD("send_buff***********\n%s\n", pstdata->databuf); + #endif + return SF_SUCCESS; + } +SINT32 sf_net_packetgrouping_disconnection(SF_DATA_ATTR_S *pstdata,SF_VOID *Param) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(Param,SF_FAILURE); + + //UINT8 i=0; + UINT16 Crc=0; + UINT8 *pData = pstdata->databuf; + SF_PDT_PARAM_STATISTICS_S *sim_info_t2 = sf_statistics_param_get(); + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + + *pData++ = 0; //ifver + *pData++ = 1; //ifver + + *pData++ = 0; //len + *pData++ = 0x14; //len + + + /*********data***********/ + *pData++ = 0x10; //CMD + *pData++ = 0x19; //CMD + + *pData++ = 17; //len + //16bytes imei + memset(pData, '\0', 16); + memcpy(pData, sim_info_t2->IMEI, strlen(sim_info_t2->IMEI)); + pData += 16; + *pData++ = 1; + + //CRC16 + Crc = makeCrc(pstdata->databuf+2, pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + + return SF_SUCCESS; + +} + SINT32 sf_net_packetanalysis_login(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam) + { + char *p = NULL; + char * p1 = NULL; + char * p2 = NULL; + cJSON *json = NULL; + cJSON *first = NULL; + cJSON *second = NULL; + cJSON *subListItem = NULL; + SINT32 ret = SF_SUCCESS; + UINT16 index = 0; + UINT16 i = 0; + UINT16 declen = 0; + char buf[256] = {0}; + //SF_CHAR decode_tempStr[128] = {0}; + SF_PDT_PARAM_CFG_S* pSfParam = (SF_PDT_PARAM_CFG_S*)pfnParam->pstParam; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = sf_statistics_param_get(); + SF_REPORT_FILE_ATTR_S *pSubReportFileAttr = sf_get_sub_report_file_attr(); + SF_URL_S *urlCfg = sf_ota_url_get(); + #ifndef SF_VERSION_RELEASE + MLOGD("recv_buff: %d byte,\n%s\n",param->dataSize,param->databuf); + #endif + ret = http_response_status_code((char*)param->databuf); + if(ret == SF_FAILURE) + return SF_DATA_ERROR_REQUEST; + + p = strchr((char*)param->databuf, '{'); + json = cJSON_Parse(p); + if (!json) + { + MLOGE("Error before: [%s]\n",cJSON_GetErrorPtr()); + cJSON_Delete(json); + return SF_DATA_ERROR_DATA_FORMAT; + } + + first = cJSON_GetObjectItem(json, "code"); + first = cJSON_GetObjectItem(json, "errCode"); + printf("...errCode = %d\n", first->valueint); + pStaticParam->bindFlag = 1; + if(first->valueint != 0) + { + data_error_collection(first->valueint); + + if(first->valueint == 10012 || first->valueint == 20013 || first->valueint == 20002) + { + pStaticParam->PicPlan = 0; + } + + if(first->valueint == 20002 || first->valueint == 20011) + { + pStaticParam->bindFlag = 0; + } + cJSON_Delete(json); + return SF_FAILURE; + } + + first = cJSON_GetObjectItem(json, "msg"); + printf("...msg = %s\n", first->valuestring); + first = cJSON_GetObjectItem(json, "data"); + + second = cJSON_GetObjectItem(first, "serverIp"); + if(second->valuestring != NULL){ + memcpy(pStaticParam->AcmIP, second->valuestring, strlen(second->valuestring)); + cJSON_Delete(json); + return SF_DATA_ERROR_IP_CHANGE; + } + + second = cJSON_GetObjectItem(first, "devResetCommand"); + if(second != NULL) + { + stLoginAcmResponse.devResetCommand = second->valueint; + printf(".devResetCommand = %d\n", stLoginAcmResponse.devResetCommand); + } + + second = cJSON_GetObjectItem(first, "did"); + if(second != NULL) + { + pStaticParam->Did = second->valueint; + //printf(".did = %d\n", stLoginAcmResponse.did); + } + + second = cJSON_GetObjectItem(first, "downloadUrl"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.downloadUrl, '\0', sizeof(stLoginAcmResponse.downloadUrl)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.downloadUrl, buf, declen); + memcpy(urlCfg->url, stLoginAcmResponse.downloadUrl, sizeof(stLoginAcmResponse.downloadUrl)); + printf(".downloadUrl = %s\n", stLoginAcmResponse.downloadUrl); + } + + second = cJSON_GetObjectItem(first, "dateFormat"); + if(second != NULL) + { + //printf("...pStaticParam->DateStyle = %d\n", pSfParam->DateStyle); + pSfParam->DateStyle = second->valueint; + } + + + second = cJSON_GetObjectItem(first, "hdCommand"); + if(second != NULL) + { + stLoginAcmResponse.hdCommand = second->valueint; + printf(".hdCommand = %d\n", stLoginAcmResponse.hdCommand); + } + + //sub hd pic + if((stLoginAcmResponse.hdCommand > 0) && (stLoginAcmResponse.hdCommand < 100)) + { + second = cJSON_GetObjectItem(first, "hdPhototVOList"); + i = pSubReportFileAttr->filecnt; + for(index = 0; index < stLoginAcmResponse.hdCommand; index++) + { + subListItem = cJSON_GetArrayItem(second, index); + +// if(cJSON_GetObjectItem(subListItem, "fileType")->valueSINT32 == 10) +// { +// stLoginAcmResponse.logCommand = 1; +// if(stLoginAcmResponse.hdCommand == 1) +// stLoginAcmResponse.hdCommand = 0; +// } +// else + { + pSubReportFileAttr->stSendFileAttr[i].enFileTye = cJSON_GetObjectItem(subListItem, "fileType")->valueSINT32; + sprintf(pSubReportFileAttr->stSendFileAttr[i].SubFileName, "%s", cJSON_GetObjectItem(subListItem, "fileName")->valuestring); + printf("enFileTye:%d, SubFileName:%s\n", pSubReportFileAttr->stSendFileAttr[i].enFileTye, + pSubReportFileAttr->stSendFileAttr[i].SubFileName); + i++; + pSubReportFileAttr->filecnt = i; + } + } + SLOGD("filecnt:%d\n", pSubReportFileAttr->filecnt); + } + + second = cJSON_GetObjectItem(first, "ip"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.ip, '\0', sizeof(stLoginAcmResponse.ip)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.ip, buf, declen); + p1 = stLoginAcmResponse.ip; + p2 = strchr(stLoginAcmResponse.ip, ':'); + pStaticParam->AlivePort = atoi(p2 + 1); + memcpy(pStaticParam->AliveIp, p1, p2 - p1); + printf("...acm ip is %s, port is %d\n", pStaticParam->AliveIp, pStaticParam->AlivePort); + } + + second = cJSON_GetObjectItem(first, "name"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.name, '\0', sizeof(stLoginAcmResponse.name)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.name, buf, declen); + printf(".name = %s\n", stLoginAcmResponse.name); + } + + second = cJSON_GetObjectItem(first, "offset"); + if(second != NULL) + { + stLoginAcmResponse.offset = second->valueint; + pSfParam->TimeZone = stLoginAcmResponse.offset/1000/3600; + printf(".TimeZone = %d\n", pSfParam->TimeZone); + } + + second = cJSON_GetObjectItem(first, "otaCommand"); + if(second != NULL) + { + stLoginAcmResponse.otaCommand = second->valueint; + printf(".otaCommand = %d\n", stLoginAcmResponse.otaCommand); + } + + second = cJSON_GetObjectItem(first, "passwd"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.passwd, '\0', sizeof(stLoginAcmResponse.passwd)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.passwd, buf, declen); + printf(".passwd = %s\n", stLoginAcmResponse.passwd); + } + + second = cJSON_GetObjectItem(first, "port"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.port, '\0', sizeof(stLoginAcmResponse.port)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.port, buf, declen); + printf(".port = %s\n", stLoginAcmResponse.port); + } + + second = cJSON_GetObjectItem(first, "sdFormatCommand"); + if(second != NULL) + { + stLoginAcmResponse.sdFormatCommand = second->valueint; + printf(".sdFormatCommand = %d\n", stLoginAcmResponse.sdFormatCommand); + } + + second = cJSON_GetObjectItem(first, "synConfigCommand"); + if(second != NULL) + { + stLoginAcmResponse.synConfigCommand = second->valueint; + printf(".synConfigCommand = %d\n", stLoginAcmResponse.synConfigCommand); + } + + #if 1 + // + second = cJSON_GetObjectItem(first, "serverIp"); + if(second->valuestring != NULL) + { + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.serverIp, buf, declen); + stLoginAcmResponse.RegionalChange = 1; + printf(".serverIp = %s\n", stLoginAcmResponse.serverIp); + } + #endif + + second = cJSON_GetObjectItem(first, "token"); + if(second->valuestring != NULL) + { + //memcpy(stLoginAcmResponse.token, second->valuestring, strlen(second->valuestring)); + memcpy(pStaticParam->Token, second->valuestring, strlen(second->valuestring)); + printf(".token = %s\n", pStaticParam->Token); + } + + #if 0 + second = cJSON_GetObjectItem(first, "uid"); + if(second != NULL) + { + stLoginAcmResponse.uid = second->valueint; + printf("...stLoginAcmResponse.uid = %d\n", stLoginAcmResponse.uid); + } + #endif + + second = cJSON_GetObjectItem(first, "leftOverPic"); + if(second != NULL) + { + stLoginAcmResponse.leftOverPic = second->valueint; + printf(".leftOverPic = %d\n", stLoginAcmResponse.leftOverPic); + if(stLoginAcmResponse.leftOverPic > 0) + pStaticParam->PicPlan = 1; + else + pStaticParam->PicPlan = 0; + } + + #if 0 + second = cJSON_GetObjectItem(first, "upload"); + if(second != NULL) + { + stLoginAcmResponse.upload = second->valueint; + printf("...stLoginAcmResponse.upload = %d\n", stLoginAcmResponse.upload); + } + #endif + + second = cJSON_GetObjectItem(first, "uploadType"); + if(second != NULL) + { + //stLoginAcmResponse.uploadType = second->valueint; + pStaticParam->UploadMode = second->valueint; + UploadMode = pStaticParam->UploadMode; + printf(".uploadtype = %d\n", pStaticParam->UploadMode); + } + + second = cJSON_GetObjectItem(first, "url"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.url, '\0', sizeof(stLoginAcmResponse.url)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.url, buf, declen); + printf(".url = %s\n", stLoginAcmResponse.url); + } + + second = cJSON_GetObjectItem(first, "userEmail"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.userEmail, '\0', sizeof(stLoginAcmResponse.userEmail)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.userEmail, buf, declen); + memcpy(pStaticParam->BindAccount, stLoginAcmResponse.userEmail, strlen(stLoginAcmResponse.userEmail)); + + printf(".userEmail = %s\n", stLoginAcmResponse.userEmail); + } + + second = cJSON_GetObjectItem(first, "uuid"); + if(second->valuestring != NULL) + { + memset(stLoginAcmResponse.uuid, '\0', sizeof(stLoginAcmResponse.uuid)); + memset(buf, '\0', sizeof(buf)); + declen = sf_http_decrypt(second->valuestring, buf, strlen(second->valuestring)); + memcpy(stLoginAcmResponse.uuid, buf, declen); + memcpy(pStaticParam->Uuid, stLoginAcmResponse.uuid, strlen(stLoginAcmResponse.uuid)); + printf(".uuids = %s\n", stLoginAcmResponse.uuid); + } + + second = cJSON_GetObjectItem(first, "date"); + if(second->valuestring != NULL) + { + memcpy(stLoginAcmResponse.date, second->valuestring, strlen(second->valuestring)); + printf(".date = %s\n", stLoginAcmResponse.date); + } + + second = cJSON_GetObjectItem(first, "maxNumberDay"); + if(second != NULL) + { + pSfParam->SendMaxNum = second->valueint; + printf(".maxNumberDay = %d\n", pSfParam->SendMaxNum); + } + + second = cJSON_GetObjectItem(first, "getPic"); + if(second != NULL) + { + stLoginAcmResponse.getPic = second->valueint; + printf(".getPic = %d\n", stLoginAcmResponse.getPic); + } + + sprintf((char *)pStaticParam->stOssCfg.szIP , "%s", stLoginAcmResponse.url); + sprintf((char *)pStaticParam->stOssCfg.szBucket, "%s", stLoginAcmResponse.port); + sprintf((char *)pStaticParam->stOssCfg.szUsername, "%s", stLoginAcmResponse.name); + sprintf((char *)pStaticParam->stOssCfg.szPassword, "%s", stLoginAcmResponse.passwd); + + /**/ + SF_PARA_TIME_S http_time; + char * indx = NULL; + indx = stLoginAcmResponse.date; + http_time.Year = atoi(indx); + indx = strchr(indx, '-'); + indx++; + http_time.Mon = atoi(indx); + indx++; + indx = strchr(indx, '-'); + indx++; + http_time.Day = atoi(indx); + indx = strchr(indx, ' '); + indx++; + http_time.Hour = atoi(indx); + indx = strchr(indx, ':'); + indx++; + http_time.Min = atoi(indx); + indx++; + indx = strchr(indx, ':'); + indx++; + http_time.Sec = atoi(indx); + + printf("http time is %d-%d-%d-%d-%d-%d\r\n", + http_time.Year, http_time.Mon, http_time.Day, http_time.Hour, http_time.Min, http_time.Sec); + + pStaticParam->httpTime.Year = http_time.Year; + pStaticParam->httpTime.Mon = http_time.Mon; + pStaticParam->httpTime.Day = http_time.Day; + pStaticParam->httpTime.Hour = http_time.Hour; + pStaticParam->httpTime.Min = http_time.Min; + pStaticParam->httpTime.Sec = http_time.Sec; //International standard time + + printf("pStaticParam http time is %d-%d-%d-%d-%d-%d\r\n", + pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day, \ + pStaticParam->httpTime.Hour, pStaticParam->httpTime.Min, pStaticParam->httpTime.Sec); + SINT32 sec = 0; + sec = sf_get_seconds(http_time);//28800000 + sec += stLoginAcmResponse.offset / 1000; + sf_get_date(sec, &rtcTime); + + printf("rtcTime is %d-%d-%d-%d-%d-%d\r\n", + rtcTime.Year, rtcTime.Mon, rtcTime.Day, rtcTime.Hour, rtcTime.Min, rtcTime.Sec); + + + + + cJSON_Delete(json); + return ret; + } + + SINT32 sf_net_packetanalysis_fileresult(SF_DATA_ATTR_S *param) + { + char *p = NULL; + char *out = NULL; + cJSON *json = NULL; + cJSON *first = NULL; + cJSON *second = NULL; + cJSON *third = NULL; + SF_URL_S *urlCfg = sf_ota_url_get(); + SINT32 ret = 0; + SINT8 index = 0; + SF_REPORT_FILE_ATTR_S *pSubReportFileAttr = sf_get_sub_report_file_attr(); + + #ifndef SF_VERSION_RELEASE + MLOGD("recv_buff: %d byte,\n%s\n",param->dataSize,param->databuf); + #endif + ret = http_response_status_code((char*)param->databuf); + if(ret == SF_FAILURE) + return SF_DATA_ERROR_REQUEST; + + p = strchr((char*)param->databuf, '{'); + json=cJSON_Parse(p); + if (!json) + { + printf("Error before: [%s]\n",cJSON_GetErrorPtr()); + cJSON_Delete(json); + return SF_DATA_ERROR_DATA_FORMAT; + } + + + first = cJSON_GetObjectItem(json, "code"); + printf("...code = %d\n", first->valueint); + + + first = cJSON_GetObjectItem(json, "errCode"); + ret = first->valueint; + printf("...errCode = %d\n", first->valueint); + + first = cJSON_GetObjectItem(json, "data"); + second = cJSON_GetObjectItem(first, "otaCommand"); + if(second != NULL) { + stLoginAcmResponse.otaCommand = second->valueint; + printf("...otaCommand = %d\n", stLoginAcmResponse.otaCommand); + } + + second = cJSON_GetObjectItem(first, "downloadUrl"); + if(second->valuestring != NULL) { + memset(stLoginAcmResponse.downloadUrl, '\0', sizeof(stLoginAcmResponse.downloadUrl)); + sf_http_decrypt(second->valuestring, stLoginAcmResponse.downloadUrl, strlen(second->valuestring)); + memcpy(urlCfg->url, stLoginAcmResponse.downloadUrl, sizeof(stLoginAcmResponse.downloadUrl)); + printf("...downloadUrl = %s\n", stLoginAcmResponse.downloadUrl); + } + + second = cJSON_GetObjectItem(first, "hdCommand"); + if(second != NULL) { + stLoginAcmResponse.hdCommand = second->valueint; + printf("...hdCommand = %d\n", stLoginAcmResponse.hdCommand); + } + + if((stLoginAcmResponse.hdCommand > 0) && (stLoginAcmResponse.hdCommand < 100)) + { + second = cJSON_GetObjectItem(first, "hdPhototVOList"); + SINT8 i = pSubReportFileAttr->filecnt; + for(index = 0; index < stLoginAcmResponse.hdCommand; index++) + { + third = cJSON_GetArrayItem(second, index); + +// if(cJSON_GetObjectItem(third, "fileType")->valueSINT32 == 10) +// { +// stLoginAcmResponse.logCommand = 1; +// if(stLoginAcmResponse.hdCommand == 1) +// stLoginAcmResponse.hdCommand = 0; +// } +// else + { + pSubReportFileAttr->stSendFileAttr[i].enFileTye = cJSON_GetObjectItem(third, "fileType")->valueSINT32; + sprintf(pSubReportFileAttr->stSendFileAttr[i].SubFileName, "%s", cJSON_GetObjectItem(third, "fileName")->valuestring); + + printf("enFileTye:%d, SubFileName:%s\n", + pSubReportFileAttr->stSendFileAttr[i].enFileTye, + pSubReportFileAttr->stSendFileAttr[i].SubFileName); + i++; + pSubReportFileAttr->filecnt = i; + } + } + SLOGD("filecnt:%d\n", pSubReportFileAttr->filecnt); + } + + cJSON_Delete(json); + free(out); + + return ret; + } + + + + SINT32 sf_net_packetanalysis_sync(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam) + { + char *p = NULL; + char *out = NULL; + cJSON *json = NULL; + cJSON *first = NULL; + cJSON *second = NULL; + int ret = 0; + //UINT8 temp = 0; + char * indx = NULL; + SF_PDT_PARAM_CFG_S* pSfParam = pfnParam->pstParam; + #ifndef SF_VERSION_RELEASE + MLOGD("recv_buff: %d byte,\n%s\n",param->dataSize,param->databuf); + #endif + ret = http_response_status_code((char*)param->databuf); + if(ret == SF_FAILURE) + return SF_DATA_ERROR_REQUEST; + p = strchr((char*)param->databuf, '{'); + json=cJSON_Parse(p); + if (!json) + { + printf("Error before: [%s]\n",cJSON_GetErrorPtr()); + cJSON_Delete(json); + return SF_DATA_ERROR_DATA_FORMAT; + } + + + first = cJSON_GetObjectItem(json, "code"); + printf("...code = %d\n", first->valueint); + + first = cJSON_GetObjectItem(json, "errCode"); + MLOGI("...errCode = %d\n", first->valueint); + if(first->valueint != 0) + { + data_error_collection(first->valueint); + cJSON_Delete(json); + return SF_FAILURE; + } + + + + first = cJSON_GetObjectItem(json, "msg"); + printf("...msg = %s\n", first->valuestring); + + first = cJSON_GetObjectItem(json, "data"); + out = cJSON_Print(first); + if(!(strstr(out, "{") && strstr(out, "}"))) { + pSfParam->ParaSync = 0; + MLOGD("...ParaSync = %d\n", pSfParam->ParaSync); + return SF_SUCCESS; + } + + second = cJSON_GetObjectItem(first, "video"); + pSfParam->CamMode = second->valueint - 1; + printf("...camera_mode = %d\n", pSfParam->CamMode); + + second = cJSON_GetObjectItem(first, "image"); + pSfParam->ImgSize = second->valueint; + printf("...img_size = %d\n", pSfParam->ImgSize); + + second = cJSON_GetObjectItem(first, "multishot"); + pSfParam->Multishot = second->valueint; + if(pSfParam->Multishot > 3) { + pSfParam->Multishot = 3; + MLOGW("Multishot [%d] is more than [1,3],so default value [3]\n",second->valueint); + } + + printf("...multishot = %d\n", pSfParam->Multishot); + + second = cJSON_GetObjectItem(first, "videoSize"); + pSfParam->VideoSize = (second->valueint) - 1; + printf("...video_size = %d\n", pSfParam->VideoSize); + + second = cJSON_GetObjectItem(first, "videoLength"); + pSfParam->VideoLenth = second->valueint; + printf("...video_lenth = %d\n", pSfParam->VideoLenth); + + #if 0 + second = cJSON_GetObjectItem(first, "videoFrameRate"); + pSfParam->VideoFrame = second->valueint; + MLOGD("...video_frame_rate = %d\n", pSfParam->VideoFrame); + + second = cJSON_GetObjectItem(first, "sendFrequency"); + pSfParam->BatchSendTimelapse = second->valueint; + MLOGD("...send_frequency = %d\n", pSfParam->BatchSendTimelapse); + #endif + second = cJSON_GetObjectItem(first, "pirswitch"); + pSfParam->PirSwitch = second->valueint; + printf("...pir_work_switch = %d\n", pSfParam->PirSwitch); + + second = cJSON_GetObjectItem(first, "pirsentivity"); + pSfParam->DigitPirSensitivity = second->valueint; + pSfParam->PirSensitivity = sf_pir_to_digit_analog(pSfParam->DigitPirSensitivity); + + printf("...DigitPirSensitivity = %d\n", pSfParam->DigitPirSensitivity); + printf("...pirsentivity = %d\n", pSfParam->PirSensitivity); + + second = cJSON_GetObjectItem(first, "delayFlag"); + pSfParam->PirDelaySwitch = second->valueint; + printf("...pir_delay_switch = %d\n", pSfParam->PirDelaySwitch); + + second = cJSON_GetObjectItem(first, "delayValue"); + indx = second->valuestring; + pSfParam->PirDelayTime.Hour = ((*indx++) - '0')*10; + pSfParam->PirDelayTime.Hour += ((*indx++) - '0'); + pSfParam->PirDelayTime.Min = ((*indx++) - '0')*10; + pSfParam->PirDelayTime.Min += ((*indx++) - '0'); + pSfParam->PirDelayTime.Sec = ((*indx++) - '0')*10; + pSfParam->PirDelayTime.Sec += ((*indx++) - '0'); + printf("...pir_delay_value = %s\n", second->valuestring); + + second = cJSON_GetObjectItem(first, "timelapseFlag"); + pSfParam->TimelapseSwitch = second->valueint; + printf("...timelapse_switch = %d\n", pSfParam->TimelapseSwitch); + + second = cJSON_GetObjectItem(first, "timelapseValue");// + indx = second->valuestring; + pSfParam->TimelapseTime.Hour = ((*indx++) - '0')*10; + pSfParam->TimelapseTime.Hour += ((*indx++) - '0'); + pSfParam->TimelapseTime.Min = ((*indx++) - '0')*10; + pSfParam->TimelapseTime.Min += ((*indx++) - '0'); + pSfParam->TimelapseTime.Sec = ((*indx++) - '0')*10; + pSfParam->TimelapseTime.Sec += ((*indx++) - '0'); + printf("...timelapse_value = %s\n", second->valuestring); + + + second = cJSON_GetObjectItem(first, "timerFlag"); + pSfParam->WorkTime1Switch = second->valueint; + printf("...work_timer1_swtich = %d\n", pSfParam->WorkTime1Switch); + + second = cJSON_GetObjectItem(first, "timerValue"); + indx = second->valuestring; + pSfParam->WorkTime[0].StartTime.Hour = ((*indx++) - '0')*10; + pSfParam->WorkTime[0].StartTime.Hour += ((*indx++) - '0'); + pSfParam->WorkTime[0].StartTime.Min = ((*indx++) - '0')*10; + pSfParam->WorkTime[0].StartTime.Min += ((*indx++) - '0'); + indx++; + pSfParam->WorkTime[0].StopTime.Hour = ((*indx++) - '0')*10; + pSfParam->WorkTime[0].StopTime.Hour += ((*indx++) - '0'); + pSfParam->WorkTime[0].StopTime.Min = ((*indx++) - '0')*10; + pSfParam->WorkTime[0].StopTime.Min += ((*indx++) - '0'); + printf("...work time1 start, h:%d, m:%d\r\n", pSfParam->WorkTime[0].StartTime.Hour, pSfParam->WorkTime[0].StartTime.Min); + printf("...work time1 stop, h:%d, m:%d\r\n", pSfParam->WorkTime[0].StopTime.Hour, pSfParam->WorkTime[0].StopTime.Min); + printf("...work_timer1_value = %s\n", second->valuestring); + + second = cJSON_GetObjectItem(first, "timerFlag2"); + pSfParam->WorkTime2Switch = second->valueint; + printf("...work_timer2_swtich = %d\n", pSfParam->WorkTime2Switch); + + second = cJSON_GetObjectItem(first, "timerValue2"); + indx = second->valuestring; + pSfParam->WorkTime[1].StartTime.Hour = ((*indx++) - '0')*10; + pSfParam->WorkTime[1].StartTime.Hour += ((*indx++) - '0'); + pSfParam->WorkTime[1].StartTime.Min = ((*indx++) - '0')*10; + pSfParam->WorkTime[1].StartTime.Min += ((*indx++) - '0'); + indx++; + pSfParam->WorkTime[1].StopTime.Hour = ((*indx++) - '0')*10; + pSfParam->WorkTime[1].StopTime.Hour += ((*indx++) - '0'); + pSfParam->WorkTime[1].StopTime.Min = ((*indx++) - '0')*10; + pSfParam->WorkTime[1].StopTime.Min += ((*indx++) - '0'); + printf("...work_timer2_value = %s\n", second->valuestring); + printf("...work time2 start, h:%d, m:%d\r\n", pSfParam->WorkTime[1].StartTime.Hour, pSfParam->WorkTime[1].StartTime.Min); + printf("...work time2 stop, h:%d, m:%d\r\n", pSfParam->WorkTime[1].StopTime.Hour, pSfParam->WorkTime[1].StopTime.Min); + + second = cJSON_GetObjectItem(first, "batteryType"); + pSfParam->BatteryType = second->valueint; + printf("...battery_type = %d\n", pSfParam->BatteryType); + + second = cJSON_GetObjectItem(first, "ledNumber"); + pSfParam->FlashLed = second->valueint; + printf("...flash_power = %d\n", pSfParam->FlashLed); + + second = cJSON_GetObjectItem(first, "stamp"); + pSfParam->StampSwitch = second->valueint; + printf("...water_stamp = %d\n", pSfParam->StampSwitch); + + second = cJSON_GetObjectItem(first, "sdcycleFlag"); + pSfParam->SdLoop = second->valueint; + printf("...cycle_recording = %d\n", pSfParam->SdLoop); + + second = cJSON_GetObjectItem(first, "dailyreportFlag"); + pSfParam->DailyReportswitch = second->valueint; + printf("...dailyreportFlag = %d\n", pSfParam->DailyReportswitch); + + second = cJSON_GetObjectItem(first, "dailyreportValue");// + indx = second->valuestring; + pSfParam->DailyReportTime.Hour = ((*indx++) - '0')*10; + pSfParam->DailyReportTime.Hour += ((*indx++) - '0'); + pSfParam->DailyReportTime.Min = ((*indx++) - '0')*10; + pSfParam->DailyReportTime.Min += ((*indx++) - '0'); + printf("...dailyreportValue = %s\n", second->valuestring); + printf("...Hour = %d\n", pSfParam->DailyReportTime.Hour); + printf("...Min = %d\n", pSfParam->DailyReportTime.Min); + if(pSfParam->DailyReportswitch == 0) + { + if(pSfParam->DailyReportTime.Hour == 0 && + pSfParam->DailyReportTime.Min == 0) + { + pSfParam->GprsMode = 1;/*realtime*/ + } + else + { + pSfParam->GprsMode = 0;/*off*/ + } + } + else + { + + if((pSfParam->DailyReportTime.Hour == 0) && (pSfParam->DailyReportTime.Min == 30)) + { + pSfParam->GprsMode = 2; + } + else if((pSfParam->DailyReportTime.Hour == 1) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 3; + } + else if((pSfParam->DailyReportTime.Hour == 2) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 4; + } + else if((pSfParam->DailyReportTime.Hour == 3) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 5; + } + else if((pSfParam->DailyReportTime.Hour == 4) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 6; + } + else if((pSfParam->DailyReportTime.Hour == 6) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 7; + } + else if((pSfParam->DailyReportTime.Hour == 12) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 8; + } + else if((pSfParam->DailyReportTime.Hour == 24) && (pSfParam->DailyReportTime.Min == 0)) + { + pSfParam->GprsMode = 9; + } + } + MLOGD("...GprsMode = %d\n", pSfParam->GprsMode); + pSfParam->ParaSync = 1; + cJSON_Delete(json); + free(out); + + MLOGD("...ParaSync = %d\n", pSfParam->ParaSync); + return SF_SUCCESS; + } + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + diff --git a/code/application/source/sf_app/code/source/dataMng/sf_transdata1.c b/code/application/source/sf_app/code/source/dataMng/sf_transdata1.c new file mode 100755 index 000000000..1ddd5c280 --- /dev/null +++ b/code/application/source/sf_app/code/source/dataMng/sf_transdata1.c @@ -0,0 +1,1722 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "sf_type.h" +#include "sf_log.h" + +#include "sf_module.h" + +#include "sf_storeMng.h" +#include "sf_systemMng.h" +#include "sf_dev_other.h" + +#include "sf_dataMng.h" +#include "sf_transdata1.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define CS_DEBUG_INFO 1 +extern SF_PARA_TIME_S rtcTime; +extern SF_CMD_QUERYPENDING_E PendingOrder; +extern UINT8 CanUpload; +extern UINT8 UploadMode; +extern UINT8 HasCommand; +extern UINT16 SubscribeRet; + + +SF_CHAR Device_id[5] = {0}; + + +//const SF_CHAR* sf_param_getqueryrequeststatusstring(UINT16 enModuleType) +//{ +// switch(enModuleType) +// { +// case SF_CMD_LOGIN_IN: +// case SF_CMD_GET_LOGIN_IN: +// return "SF_CMD_LOGIN_IN"; +// case SF_CMD_REPORT_STATE: +// case SF_CMD_GET_REPORT_STATE: +// return "SF_CMD_REPORT_STATE"; +// case SF_CMD_PHOTO_RESULT: +// case SF_CMD_GET_PHOTO_RESULT: +// return "SF_CMD_PHOTO_RESULT"; +// case SF_CMD_QUERYPENDING_CMD: +// case SF_CMD_GET_QUERYPENDING_CMD: +// return "SF_CMD_QUERYPENDING_CMD"; +// case SF_CMD_QUERYPENDING_PARAM: +// case SF_CMD_GET_QUERYPENDING_PARAM: +// return "SF_CMD_QUERYPENDING_PARAM"; +// case SF_CMD_REPORT_RESULT: +// case SF_CMD_GET_REPORT_RESULT: +// return "SF_CMD_REPORT_RESULT"; +// case SF_CMD_TRIGGER: +// case SF_CMD_GET_TRIGGER: +// return "SF_CMD_TRIGGER"; +// case SF_CMD_DISCON_SEND: +// return "SF_CMD_DISCON_SEND"; +// default: +// return "Unknown"; +// } +//} +static SINT32 packet_log_printf(UINT8 *pbuf,UINT16 lenth) +{ + UINT16 i= 0; + for(i = 0;i < lenth;i++) + { + if(i%5 == 0) + printf("[%02d,%02d] = {",i,((lenth - i) < 5)?(lenth-1):(i+4)); + + if((i+1)%5 == 0 || (i+1) == lenth) + printf("0x%02x}\n",*pbuf++); + else + printf("0x%02x,",*pbuf++); + } + return SF_SUCCESS; + +} +static SINT32 packet_gps_parse(char *pstring,SF_PDT_PARAM_STATISTICS_S *pStaticParam) +{ + *pstring++ = pStaticParam->Latitude[9]; + *pstring++ = pStaticParam->Latitude[0]; + *pstring++ = pStaticParam->Latitude[1]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Latitude[2]; + *pstring++ = pStaticParam->Latitude[3]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Latitude[5]; + *pstring++ = pStaticParam->Latitude[6]; + *pstring++ = '-'; + + *pstring++ = pStaticParam->Longitude[10]; + *pstring++ = pStaticParam->Longitude[0]; + *pstring++ = pStaticParam->Longitude[1]; + *pstring++ = pStaticParam->Longitude[2]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Longitude[3]; + *pstring++ = pStaticParam->Longitude[4]; + *pstring++ = '.'; + *pstring++ = pStaticParam->Longitude[6]; + *pstring++ = pStaticParam->Longitude[7]; + *pstring++ = '\0'; + +// *pstring++ = 'N'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '-'; + +// *pstring++ = 'E'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '.'; +// *pstring++ = '2'; +// *pstring++ = '2'; +// *pstring++ = '\0'; + return SF_SUCCESS; +} + +SINT32 sf_packetgrouping_login(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + UINT8 i=0; + UINT8 *pData = pstdata->databuf; + UINT16 Crc=0; + UINT16 interfaceVer = 10; + UINT8 signalLevel=0; + + SF_PDT_PARAM_CFG_S *pstParam = pfnParam->pstParam; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + SF_CHAR version[12] = {0}; + SF_STORE_ATTR_S storeattrs; + + sf_sys_software_version_get(version); + + sf_sd_info_get(&storeattrs); + if(storeattrs.SDStatus != 0) + { + storeattrs.SDTotalSize = 0; + storeattrs.SDFree = 0; + } + + sf_4G_signal_level_get(pStaticParam->netGeneration,pStaticParam->SimSignal,&signalLevel); + if(signalLevel == 4) + signalLevel = 31; + else if(signalLevel == 3) + signalLevel = 13; + else if(signalLevel == 2) + signalLevel = 7; + + MLOGD("signalLevel:%d, SDTotalSize:%d, SDFree:%d\n", signalLevel, storeattrs.SDTotalSize, storeattrs.SDFree); + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + *pData++ = 0; + *pData++ = 0; + *pData++ = 0; + *pData++ = 0; + *pData++ = 0x10; //CMD + *pData++ = 0x00; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x01; //SEQ + + *pData++ = 0x00; //upload len, re calculate at end of the function + *pData++ = 0x00; //upload len, re calculate at end of the function + *pData++ = (UINT8)((interfaceVer&0xff00)>>8);; //interface ver + *pData++ = (UINT8)(interfaceVer&0x00ff); //interface ver + for(i=0; i<16; i++) //imei + *pData++ = pStaticParam->IMEI[i]; + + for(i=0;i<16;i++) + *pData++ = 0; //usrname + + for(i=0;i<16;i++) + *pData++ = 0; //password + + *pData++ = 0; + *pData++ = signalLevel; //csq + *pData++ = pStaticParam->BatRemainCap; //bat level + + *pData++ = (UINT8)((storeattrs.SDTotalSize) >>8 & 0xFF); //SD total size high 8bit + *pData++ = (UINT8)((storeattrs.SDTotalSize) & 0xFF); //SD total size low 8bit + *pData++ = (UINT8)((storeattrs.SDFree) >>8 & 0xFF); //SD free size high 8bit + *pData++ = (UINT8)((storeattrs.SDFree) & 0xFF); //SD free size low 8bit + + *pData++ = pStaticParam->FcTemper;//fahrenheit FC_temper + + *pData++ = (UINT8)((pStaticParam->SdTotalFile) >>8 & 0xFF); //total pic high 8 bit + *pData++ = (UINT8)((pStaticParam->SdTotalFile) & 0xFF); //total pic low 8 bit + *pData++ = (UINT8)((pStaticParam->SendPicDayCnt) >>8 & 0xFF); //send pic total high 8 bit + *pData++ = (UINT8)((pStaticParam->SendPicDayCnt) & 0xFF); //send pic total low 8 bit + *pData++ = 0; + *pData++ = (UINT8)((pStaticParam->TriggerTimes) >>8 & 0xFF); //trigger time high 8 bit + *pData++ = (UINT8)((pStaticParam->TriggerTimes) & 0xFF); //trigger time low 8 bit + + for(i=0;i<12;i++) //software ver + *pData++ = version[i]; + + *pData++ = pstParam->ParaSync; //cfg update flag + *pData++ = pStaticParam->startup; //start up type + *pData++ = 0; //error1 + *pData++ = 0; //error2 + *pData++ = 0; //error3 + *pData++ = 0; //error4 + + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2, pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + + #if CS_DEBUG_INFO + MLOGD("[LOGIN_IN] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + + #endif + + return SF_SUCCESS; + +} + +SINT32 sf_packetgrouping_fileresult(SF_DATA_ATTR_S *pstdata, SF_PDT_PARAM_CFG_S *pstParam,SF_FILE_ATTR_S *pstfileAttr) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstfileAttr,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstfileAttr->thumbfileName,SF_FAILURE); + + UINT8 i=0; + UINT8 *pData = pstdata->databuf; + UINT16 Crc=0; + SF_CHAR fileName[128] = { 0 }; + SF_CHAR fileNameVideo[32] = { 0 }; + UINT8 fileType = 0; + + if(pstfileAttr->enFileTye == SF_FILE_TYPE_PIC_SMALL) + { + sprintf(fileName, "thumb_%s", pstfileAttr->thumbfileName); + fileType = 1; + } + else + sprintf(fileName, "%s", pstfileAttr->thumbfileName); + + if(pstfileAttr->enFileTye == SF_FILE_TYPE_PIC_VIDEO) + { + if(pstParam->VideoSize == SF_VIDEO_SIZE_1080) + fileType = 6; + else if(pstParam->VideoSize == SF_VIDEO_SIZE_720) + fileType = 4; + else if(pstParam->VideoSize == SF_VIDEO_SIZE_WVGA) + fileType = 2; + } + + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + + *pData++ = Device_id[0]; + *pData++ = Device_id[1]; + *pData++ = Device_id[2]; + *pData++ = Device_id[3]; + *pData++ = 0x10; //CMD + *pData++ = 0x04; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x01; //seq + + *pData++ = 0x00; //负载长度 + *pData++ = 0x58; //负载长度 + + *pData++ = (rtcTime.Year>>8)&0XFF; //Year + *pData++ = rtcTime.Year&0xFF; //Year + *pData++ = rtcTime.Mon; //month + *pData++ = rtcTime.Day; //Day + *pData++ = rtcTime.Hour; //Hour + *pData++ = rtcTime.Min; //minute + *pData++ = rtcTime.Sec; //second + + *pData++ = fileType; //file type + *pData++ = sf_data_transfer_mode_get(); //upload type:1=ftp,2=oss + + *pData++ = (pstfileAttr->thumbfileSize>>24)&0XFF; //file size + *pData++ = (pstfileAttr->thumbfileSize>>16)&0XFF; //file size + *pData++ = (pstfileAttr->thumbfileSize>>8)&0XFF; //file size + *pData++ = pstfileAttr->thumbfileSize&0XFF; //file size + + MLOGD("report acm file name:%s, file size:%d, file type:%d\n", fileName, pstfileAttr->thumbfileSize, fileType); + for(i=0;i<34;i++) //filename + *pData++ = fileName[i]; + + if(pstfileAttr->enFileTye == SF_FILE_TYPE_PIC_VIDEO) + { + *pData++ = 2; + memcpy(fileNameVideo, pstfileAttr->thumbfileName, strlen(pstfileAttr->thumbfileName)-4); + sprintf(fileName, "S%s.MP4", fileNameVideo+1); + MLOGD("bind file name:%s\n", fileName); + for(i=0;i<39;i++) //filename + *pData++ = fileName[i]; + } + else + { + *pData++ = 0; //Bind thumbnails + for(i=0;i<39;i++) //filename + *pData++ = 0; + } + + *pData++ = 0; + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2,pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + #if CS_DEBUG_INFO + MLOGD("[PHOTO_RESULT] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + #endif + return SF_SUCCESS; + +} + + +SINT32 sf_packetgrouping_get_bind_account(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam) +{ + + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + UINT8 i=0; + UINT8 *pData = pstdata->databuf; + UINT16 Crc=0; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + MLOGD("IMEI:%s\n", pStaticParam->IMEI); + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + *pData++ = Device_id[0]; + *pData++ = Device_id[1]; + *pData++ = Device_id[2]; + *pData++ = Device_id[3]; + *pData++ = 0x10; //CMD + *pData++ = 0x0e; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x01; //SEQ + + *pData++ = 0x00; //upload len, re calculate at end of the function + *pData++ = 0x00; //upload len, re calculate at end of the function + + *pData++ = 0x00; + *pData++ = 0x01; //1 :get bind account + + for(i=0; i<16; i++) //imei + *pData++ = pStaticParam->IMEI[i]; + + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2, pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + #if CS_DEBUG_INFO + MLOGD("[BIND_ACCOUNT] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + #endif + + return SF_SUCCESS; + +} + +SINT32 sf_packetgrouping_query_cmd(SF_DATA_ATTR_S *pstdata) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + + UINT16 Crc=0; + UINT8 *pData = pstdata->databuf; + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + + *pData++ = Device_id[0]; + *pData++ = Device_id[1]; + *pData++ = Device_id[2]; + *pData++ = Device_id[3]; + + *pData++ = 0x10; //CMD + *pData++ = 0x06; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x01; //SEQ + *pData++ = 0x00; //Payload len + *pData++ = 0x7; //Payload len + + *pData++ = (rtcTime.Year>>8)&0XFF; //Year + *pData++ = rtcTime.Year&0xFF; //Year + *pData++ = rtcTime.Mon; //month + *pData++ = rtcTime.Day; //Day + *pData++ = rtcTime.Hour; //Hour + *pData++ = rtcTime.Min; //minute + *pData++ = rtcTime.Sec; //second + + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2,pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + #if CS_DEBUG_INFO + MLOGD("[QUERYPENDING_CMD] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + #endif + + return SF_SUCCESS; + +} + + +SINT32 sf_packetgrouping_query_cmd_param(SF_DATA_ATTR_S *pstdata) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + UINT16 Crc=0; + UINT8 *pData = pstdata->databuf; + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + + *pData++ = Device_id[0]; + *pData++ = Device_id[1]; + *pData++ = Device_id[2]; + *pData++ = Device_id[3]; + + *pData++ = 0x10; //CMD + *pData++ = 0x08; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x01; //SEQ + *pData++ = 0x00; //负载长度 + *pData++ = 0x9; //负载长度 + + *pData++ = (PendingOrder>>8)&0XFF; + *pData++ = PendingOrder&0xFF; //comand + + + *pData++ = (rtcTime.Year>>8)&0XFF; //Year + *pData++ = rtcTime.Year&0xFF; //Year + *pData++ = rtcTime.Mon; //month + *pData++ = rtcTime.Day; //Day + *pData++ = rtcTime.Hour; //Hour + *pData++ = rtcTime.Min; //minute + *pData++ = rtcTime.Sec; //second + + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2,pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + #if CS_DEBUG_INFO + MLOGD("[QUERYPENDING_PARAM] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + #endif + + return SF_SUCCESS; + +} + + +SINT32 sf_packetgrouping_cmd_report(SF_DATA_ATTR_S *pstdata, SF_FN_PARAM_S *pfnParam, SF_FILE_ATTR_S *pstfileAttr) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstfileAttr,SF_FAILURE); + + UINT8 i=0; + UINT8 *pData = pstdata->databuf; + UINT16 Crc=0; + UINT8 fileType = 0; + SF_PDT_PARAM_CFG_S *pstparam = pfnParam->pstParam; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + + *pData++ = Device_id[0]; + *pData++ = Device_id[1]; + *pData++ = Device_id[2]; + *pData++ = Device_id[3]; + + *pData++ = 0x10; //CMD + *pData++ = 0x0a; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x01; //SEQ + *pData++ = 0x00; //payload len + *pData++ = 0x9; //pauload len + + *pData++ = (PendingOrder>>8)&0XFF; + *pData++ = PendingOrder&0xFF; //comand + if(PendingOrder == SF_CMD_QUERYPENDING_GETPICTURE) + { + //not always 0; 1 fail by net error; 2 fail by no pic/video file + *pData++ = (SubscribeRet>>8)&0XFF; + *pData++ = SubscribeRet&0xFF; + } + else + { + *pData++ = 0x00; + *pData++ = 0x00; + } + + switch(PendingOrder) + { + case SF_CMD_QUERYPENDING_GETCFGFILE: + break; + + case SF_CMD_QUERYPENDING_GETPICTURE: + if(pstfileAttr->enFileTye == SF_FILE_TYPE_VIDEO) + fileType = 2; + else if(pstfileAttr->enFileTye == SF_FILE_TYPE_PIC_BIG) + fileType = 0; + else if(pstfileAttr->enFileTye == SF_FILE_TYPE_GPS) + fileType = 3; + + *pData++ = fileType; //upload type + *pData++ = sf_data_transfer_mode_get(); //upload mode*/ + *pData++ = (UINT8)((pstfileAttr->thumbfileSize>>24)&0xff); /*file size*/ + *pData++ = (UINT8)((pstfileAttr->thumbfileSize>>16)&0xff); /**/ + *pData++ = (UINT8)((pstfileAttr->thumbfileSize>>8)&0xff); /**/ + *pData++ = (UINT8)(pstfileAttr->thumbfileSize&0xff); /**/ + + for(i=0;i<35;i++) + *pData++ = pstfileAttr->thumbfileName[i]; /*HD filename*/ + + if(pstfileAttr->enFileTye != SF_FILE_TYPE_GPS) + { + /* send success bind 0; send failed bind 1*/ + + *pData++ = 1; + for(i=0;i<39;i++) + *pData++ = pStaticParam->stSubscribe.pSubscribe[0].subscribeFileName[i]; + } + else + { + *pData++ = 0; + for(i=0;i<39;i++) + *pData++ = pStaticParam->stSubscribe.pSubscribe[0].subscribeFileName[i]; + } + MLOGD("SubscribeFileName:%s\n", pStaticParam->stSubscribe.pSubscribe[0].subscribeFileName); + free(pStaticParam->stSubscribe.pSubscribe); + break; + + case SF_CMD_QUERYPENDING_GETSTATUS: + break; + + case SF_CMD_QUERYPENDING_GETSLEEPTIME: + break; + + case SF_CMD_QUERYPENDING_REBOOT: + break; + + case SF_CMD_QUERYPENDING_SETSYSTEMTIME: + break; + + case SF_CMD_QUERYPENDING_SETCAMERAMODE: + case SF_CMD_QUERYPENDING_GETCAMERAMODE: + *pData++ = pstparam->CamMode+1; + *pData++ = pstparam->ImgSize; + *pData++ = pstparam->Multishot; + *pData++ = pstparam->Zoom+1; + *pData++ = pstparam->VideoSize+1; + *pData++ = pstparam->VideoLenth; + *pData++ = 1; + *pData++ = 1; + + SLOGI("CameraMode = [%d],ImgSize = [%d],Multishot = [%d],Zoom = [%d],\n " + "VideoSize = [%d],VideoLenth = [%d],VideoFrame = [%d],LightFreq = [%d]\n", + pstparam->CamMode, + pstparam->ImgSize, + pstparam->Multishot, + pstparam->Zoom, + pstparam->VideoSize, + pstparam->VideoLenth, + pstparam->VideoFrame, + pstparam->LightFreq); + break; + + case SF_CMD_QUERYPENDING_SETWORKMODE: + case SF_CMD_QUERYPENDING_GETMODECFG: + + *pData++ = pstparam->TimelapseSwitch; + *pData++ = pstparam->TimelapseTime.Hour/10+'0'; + *pData++ = pstparam->TimelapseTime.Hour%10+'0'; + *pData++ = pstparam->TimelapseTime.Min/10+'0'; + *pData++ = pstparam->TimelapseTime.Min%10+'0'; + *pData++ = pstparam->TimelapseTime.Sec/10+'0'; + *pData++ = pstparam->TimelapseTime.Sec%10+'0'; + + /* + if(pstparam->PirSwitch == 0) + *pData++ = 0; + else if(pstparam->PirSensitivity == 0) + *pData++ = 3; + else if(pstparam->PirSensitivity == 1) + *pData++ = 2; + else if(pstparam->PirSensitivity == 2) + *pData++ = 1; + */ + *pData++ = pstparam->DigitPirSensitivity; + *pData++ = pstparam->PirDelaySwitch; + *pData++ = pstparam->PirDelayTime.Hour/10+'0'; + *pData++ = pstparam->PirDelayTime.Hour%10+'0'; + *pData++ = pstparam->PirDelayTime.Min/10+ '0'; + *pData++ = pstparam->PirDelayTime.Min%10+ '0'; + *pData++ = pstparam->PirDelayTime.Sec/10+ '0'; + *pData++ = pstparam->PirDelayTime.Sec%10+ '0'; + + *pData++ = pstparam->WorkTime1Switch; + *pData++ = pstparam->WorkTime[0].StartTime.Hour/10+'0'; + *pData++ = pstparam->WorkTime[0].StartTime.Hour%10+'0'; + *pData++ = pstparam->WorkTime[0].StartTime.Min/10+ '0'; + *pData++ = pstparam->WorkTime[0].StartTime.Min%10+ '0'; + *pData++ = '-'; + *pData++ = pstparam->WorkTime[0].StopTime.Hour/10+'0'; + *pData++ = pstparam->WorkTime[0].StopTime.Hour%10+'0'; + *pData++ = pstparam->WorkTime[0].StopTime.Min/10+ '0'; + *pData++ = pstparam->WorkTime[0].StopTime.Min%10+ '0'; + + *pData++ = pstparam->WorkTime2Switch; + *pData++ = pstparam->WorkTime[1].StartTime.Hour/10+'0'; + *pData++ = pstparam->WorkTime[1].StartTime.Hour%10+'0'; + *pData++ = pstparam->WorkTime[1].StartTime.Min/10+ '0'; + *pData++ = pstparam->WorkTime[1].StartTime.Min%10+ '0'; + *pData++ = '-'; + *pData++ = pstparam->WorkTime[1].StopTime.Hour/10+'0'; + *pData++ = pstparam->WorkTime[1].StopTime.Hour%10+'0'; + *pData++ = pstparam->WorkTime[1].StopTime.Min/10+ '0'; + *pData++ = pstparam->WorkTime[1].StopTime.Min%10+ '0'; + + *pData++ = pstparam->PirSwitch; + +#if 1 + if(pstparam->GprsMode == 0) + { + pstparam->DailyReportswitch = 0; + pstparam->DailyReportTime.Hour = 24; + pstparam->DailyReportTime.Min = 0; + } + else if(pstparam->GprsMode == 1) + { + pstparam->DailyReportswitch = 0; + pstparam->DailyReportTime.Hour = 0; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 2) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 0; + pstparam->DailyReportTime.Min = 30; + + } + else if(pstparam->GprsMode == 3) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 1; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 4) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 2; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 5) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 3; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 6) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 4; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 7) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 6; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 8) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 12; + pstparam->DailyReportTime.Min = 0; + + } + else if(pstparam->GprsMode == 9) + { + pstparam->DailyReportswitch = 1; + pstparam->DailyReportTime.Hour = 24; + pstparam->DailyReportTime.Min = 0; + + } +#endif + *pData++ = pstparam->DailyReportswitch;; + *pData++ = pstparam->DailyReportTime.Hour/10+'0'; + *pData++ = pstparam->DailyReportTime.Hour%10+'0'; + *pData++ = pstparam->DailyReportTime.Min/10+ '0'; + *pData++ = pstparam->DailyReportTime.Min%10+ '0'; + + + + *pData++ = pstparam->NightMode; + + *pData++ = pstparam->GprsMode; + *pData++ = pstparam->FlashLed; + *pData++ = pstparam->SendVideo;//pstparam->SendVideo; + *pData++ = pstparam->SendPhoto;//pstparam->SendPhoto; + *pData++ = pstparam->SendMultishot;//pstparam->SendBrustPic; + + break; + + case SF_CMD_QUERYPENDING_SETOTHER: + case SF_CMD_QUERYPENDING_GETOTHERCFG: + *pData++ = pstparam->SendMaxNum; //pstparam->MmsMax; + *pData++ = 0; //pstparam->Tvout; + *pData++ = 0; //pstparam->Audiorecord; + *pData++ = pstparam->StampSwitch; //pstparam->Stamp; + *pData++ = 0; //pstparam->Startuptone; + *pData++ = 0; //pstparam->Keyboard; + *pData++ = 0; //pstparam->CameraIDflag; + for(i=0;i<13;i++) + *pData++ = 0; //pstparam->CameraID[i]; + *pData++ = 0; //pstparam->CamerapasswdFlag; + for(i=0;i<6;i++) + *pData++ = 0; //pstparam->Camerapasswd[i]; + + *pData++ = pstparam->SdLoop; //pstparam->SDcycleRecord; + *pData++ = 0; //pstparam->TriggerLogs; + *pData++ = pstparam->DateStyle; //pstparam->DateStyle; + *pData++ = pstparam->GPSFlag; //pstparam->GPSflag; + { + char stringGPS[21] = {0}; + packet_gps_parse(stringGPS,pStaticParam); + MLOGD("stringGPS = [%s]\n",stringGPS); + for(i=0;i<21;i++) + *pData++ = stringGPS[i]; + } + + + *pData++ = pstparam->BatteryType; + MLOGD("SendMaxNum = [%d],StampSwitch = [%d],SdLoop = [%d],\n GPSFlag = [%d],battery = [%d],DateStyle = [%d]\n", + pstparam->SendMaxNum, + pstparam->StampSwitch, + pstparam->SdLoop, + pstparam->GPSFlag, + pstparam->BatteryType, + pstparam->DateStyle); + + break; + + case SF_CMD_QUERYPENDING_SETSERVER: + break; + + case SF_CMD_QUERYPENDING_UPLOADCFGFILE: + break; + + case SF_CMD_QUERYPENDING_GETSERVERPAREAM: + MLOGD("AcmIP:%s\n", pStaticParam->AcmIP); + for(i=0;i<26;i++) + *pData++ = pStaticParam->AcmIP[i]; + for(i=0;i<5;i++) + *pData++ = 0; + break; + + case SF_CMD_QUERYPENDING_SETUPLOADPICSIZE: + break; + + case SF_CMD_QUERYPENDING_GETUPLOADPICSIZE: + *pData++ = pstparam->SendPicSize; + break; + + case SF_CMD_QUERYPENDING_SYNPARAM: + break; + + case SF_CMD_QUERYPENDING_VERSIONUPDATE: + break; + + case SF_CMD_QUERYPENDING_GETGPSINFO: + { char stringGPS[21] = {0}; + packet_gps_parse(stringGPS,pStaticParam); + for(i=0;i<21;i++) + *pData++ = stringGPS[i]; + } + break; + + case SF_CMD_QUERYPENDING_SETGPSANTITHIEF: + *pData++ = pstparam->GPSAntitheftFlag; + break; + case SF_QUERYPENDING_COMMAND_RESET: + *pData++ = pstparam->ResetFlag; + break; + case SF_QUERYPENDING_COMMAND_FORMAT: + *pData++ = pstparam->FormateFlag; + + break; + default: + break; + + } + *pData++ = (rtcTime.Year>>8)&0XFF; //Year + *pData++ = rtcTime.Year&0xFF; //Year + *pData++ = rtcTime.Mon; //month + *pData++ = rtcTime.Day; //Day + *pData++ = rtcTime.Hour; //Hour + *pData++ = rtcTime.Min; //minute + *pData++ = rtcTime.Sec; //second + SLOGI("TIME:%d/%d/%d %d:%d:%d\n",rtcTime.Year, rtcTime.Mon, rtcTime.Day, rtcTime.Hour, rtcTime.Min, rtcTime.Sec); + + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2,pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + #if CS_DEBUG_INFO + MLOGD("[REPORT_RESULT] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + #endif + + return SF_SUCCESS; + +} +SINT32 sf_packetgrouping_disconnection(SF_DATA_ATTR_S *pstdata,SF_VOID *Param) +{ + SF_COMM_CHECK_POINTER(pstdata,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstdata->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(Param,SF_FAILURE); + + UINT16 Crc=0; + UINT8 *pData = pstdata->databuf; + + *pData++ = 0x55; //CMD + *pData++ = 0xAA; + + *pData++ = Device_id[0]; + *pData++ = Device_id[1]; + *pData++ = Device_id[2]; + *pData++ = Device_id[3]; + + *pData++ = 0x10; //CMD + *pData++ = 0x0c; //CMD + *pData++ = 0x00; //SEQ + *pData++ = 0x02; //seq + + *pData++ = 0x00; //负载长度 + *pData++ = 0x02; //负载长度 + + *pData++ = 0x00;//1 + *pData++ =*(UINT8*)Param; + + + pstdata->databuf[10] = ((pData-(pstdata->databuf+12))>>8)&0XFF; + pstdata->databuf[11] = (pData-(pstdata->databuf+12))&0xFF; + + Crc = makeCrc(pstdata->databuf+2,pData-(pstdata->databuf+2)); + *pData++ = (UINT8)((Crc&0xff00)>>8); + *pData++ = (UINT8)((Crc&0x00ff)); + *pData++ = 0xef; + *pData++ = 0xef; + *pData++ = 0x1a; + *pData++ = '\r'; + *pData++ = '\0'; + pstdata->dataSize = pData-pstdata->databuf; + #if CS_DEBUG_INFO + MLOGD("[DISCON_SEND] Send:\n"); + packet_log_printf(pstdata->databuf,(pstdata->dataSize)-2); + #endif + return SF_SUCCESS; + +} + +SINT32 sf_MultiPacket_Parsing(UINT16 enCmdID,UINT16 *pdatahead,SF_DATA_ATTR_S *pdatattr) +{ + UINT16 i=0,j=0; + UINT16 cmdID=0; + UINT16 datahead[3] = {0}; + UINT16 datatail[3] = {0}; + while(i < SF_TTYUSB_RECV_MAX) + { + if(pdatattr->databuf[i] == 0x55 && pdatattr->databuf[i+1] == 0xAA) + { + datahead[j] = i; + } + else if(pdatattr->databuf[i] == 0xEF && pdatattr->databuf[i+1] == 0xEF) + { + datatail[j] = i+1; + j++; + } + i++; + } + + for(i=0;i<3;i++) + { + MLOGD("i= %d\n",i); + if(datahead[i] == 0) + continue; + if(datatail[i] == 0) + continue; + if((datatail[i]-datahead[i]+1) <= 4) + continue; + + cmdID = (pdatattr->databuf[datahead[i]+6]<<8)+pdatattr->databuf[datahead[i]+7]; + MLOGD("cmdID[%#X] != enCmdID[%#X] is %d\n",cmdID, enCmdID,cmdID != enCmdID); + if(cmdID != enCmdID) + continue; + + *pdatahead = datahead[i]; + pdatattr->dataSize = (datatail[i]-datahead[i]+1); + } + + MLOGD("HEAD = %d,size :%d\n",*pdatahead,pdatattr->dataSize); + if(pdatattr->dataSize <= 4) + return SF_FAILURE; + +#if CS_DEBUG_INFO + + MLOGD(" recv:\n"); + packet_log_printf(&pdatattr->databuf[(*pdatahead)],pdatattr->dataSize); +#endif + return SF_SUCCESS; + + +} +SINT32 sf_packetanalysis_login(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + SINT16 s16Ret = SF_SUCCESS; + UINT16 i=0; + UINT16 cmdID=0; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 result=0; + UINT16 head = 0; + UINT8 *pData = 0; + + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + s16Ret = sf_MultiPacket_Parsing(0x1001,&head,param); + if(s16Ret != SF_SUCCESS) + return SF_DATA_ERROR_REQUEST; + + + pData = (UINT8*)param->databuf+head+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + + memset(pStaticParam->stOssCfg.szIP, '\0', sizeof(pStaticParam->stOssCfg.szIP)); + memset(pStaticParam->stOssCfg.szBucket, '\0', sizeof(pStaticParam->stOssCfg.szBucket)); + memset(pStaticParam->stOssCfg.szUsername, '\0', sizeof(pStaticParam->stOssCfg.szUsername)); + memset(pStaticParam->stOssCfg.szPassword, '\0', sizeof(pStaticParam->stOssCfg.szPassword)); + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; //cmd ID + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //payload len + result=*pData++; result = result<<8 | *pData++; //result + + for(i=0;i<4;i++) //device ID + Device_id[i] = *pData++; + MLOGD("Device_id[0x%x,0x%x,0x%x,0x%x] \n",Device_id[0],Device_id[1],Device_id[2],Device_id[3]); + MLOGD("cmdID= 0x%x,len = 0x%x result = 0x%x \n",cmdID, len, result); + + if(result == 1) + return SF_FAILURE; + + pStaticParam->httpTime.Year = *pData++; + pStaticParam->httpTime.Year = pStaticParam->httpTime.Year <<8 | *pData++; + pStaticParam->httpTime.Mon = *pData++; + pStaticParam->httpTime.Day = *pData++; + pStaticParam->httpTime.Hour = *pData++; + pStaticParam->httpTime.Min = *pData++; + pStaticParam->httpTime.Sec = *pData++; //International standard time + + UploadMode = *pData++; //upload mode + + for(i=0;i<60;i++) //OSS_IP + pStaticParam->stOssCfg.szIP[i] = *pData++; + for(i=0;i<24;i++) //OSS_BUCKET + pStaticParam->stOssCfg.szBucket[i] = *pData++; + for(i=0;i<32;i++) //OSS_USENAME + pStaticParam->stOssCfg.szUsername[i] = *pData++; + for(i=0;i<48;i++) //OSS_PASSWORD + pStaticParam->stOssCfg.szPassword[i] = *pData++; + + CanUpload = *pData++; + HasCommand = *pData++; + + MLOGD("HasCommand =%d Canupload =%d updateMode =%d\n", HasCommand, CanUpload, UploadMode); + + MLOGD("OSS_IP: [%s]\n",pStaticParam->stOssCfg.szIP); + MLOGD("OSS_BUCKET: [%s]\n",pStaticParam->stOssCfg.szBucket); + MLOGD("OSS_USENAME: [%s]\n",pStaticParam->stOssCfg.szUsername); + MLOGD("OSS_PASSWORD: [%s]\n",pStaticParam->stOssCfg.szPassword); + MLOGD("TIME:%d/%d/%d %d:%d:%d\n", pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day, pStaticParam->httpTime.Hour, pStaticParam->httpTime.Min, pStaticParam->httpTime.Sec); + + rtcTime.Year = *pData++; + rtcTime.Year = rtcTime.Year <<8 | *pData++; + rtcTime.Mon = *pData++; + rtcTime.Day = *pData++; + rtcTime.Hour = *pData++; + rtcTime.Min = *pData++; + rtcTime.Sec = *pData++; //local time + + SLOGD("TIME:%d/%d/%d %d:%d:%d\n", rtcTime.Year, rtcTime.Mon, rtcTime.Day, rtcTime.Hour, rtcTime.Min, rtcTime.Sec); + return result; + +} + +SINT32 sf_packetanalysis_fileresult(SF_DATA_ATTR_S *param) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + + UINT8 i = 0; + UINT8 Temp = 0; + UINT8 *pData = (UINT8*)param->databuf; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 cmdID = 0; + UINT16 result = 0; + + + while(i < SF_TTYUSB_RECV_MAX) + { + if(param->databuf[i] == 0x55 && param->databuf[i+1] == 0xAA) + break; + i++; + } + if(i > SF_TTYUSB_RECV_MAX) + return SF_DATA_ERROR_REQUEST; + + pData = (UINT8*)param->databuf+i; + Temp = i; + + #if CS_DEBUG_INFO + MLOGD("[PHOTO_RESULT] recv:\n"); + packet_log_printf(pData,50); + #endif + + pData = (UINT8*)param->databuf+Temp+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; // 回复的登录指令 + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //负载长度 + result=*pData++; result = result<<8 | *pData++; //错误码 + + MLOGD("cmdID= 0x%x,len = 0x%x result = 0x%x \n",cmdID, len, result); + if(result != 0) + return SF_DATA_ERROR_FILE_SEND; + + return SF_SUCCESS; + +} + + +SINT32 sf_packetanalysis_query_cmd(SF_DATA_ATTR_S *param) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + + UINT16 i=0; + UINT8 Temp = 0; + UINT8 *pData = (UINT8*)param->databuf; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 cmdID = 0; + UINT16 result = 0; + + + while(i < SF_TTYUSB_RECV_MAX) + { + if(param->databuf[i] == 0x55 && param->databuf[i+1] == 0xAA) + break; + //printf("[SF_CMD_QUERYPENDING_CMD] recivedata[%d,0x%x]\n",i,param->databuf[i]); + i++; + } + if(i > SF_TTYUSB_RECV_MAX) + return SF_DATA_ERROR_REQUEST; + + pData = (UINT8*)param->databuf+i; + Temp = i; + + #if CS_DEBUG_INFO + MLOGD("[QUERYPENDING_CMD] recv:\n"); + packet_log_printf(pData,50); + #endif + + pData = (UINT8*)param->databuf+Temp+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; // cam id + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //payload len + result =*pData++; result = result<<8 | *pData++; //result + + MLOGD("cmdID= 0x%x,len = 0x%x result = 0x%x \n",cmdID,len,result); + if(cmdID != 0x1007) + return SF_DATA_ERROR_REQUEST; + + if(result != 0) + return SF_DATA_ERROR_REQUEST; + + PendingOrder = *pData++; + PendingOrder = PendingOrder <<8 | *pData++; /*pending order*/ + + //MLOGD("Command:0x%x \n", PendingOrder); + + return SF_SUCCESS; + +} + + +SINT32 sf_packetanalysis_query_cmd_param(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + UINT8 Temp = 0; + UINT8 *pData = (UINT8*)param->databuf; + UINT8 j= 0; + UINT16 i= 0; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 result=0; + UINT16 cmdID = 0; + UINT16 command = 0; + SINT16 s16Ret = SF_SUCCESS; + UINT16 temPir = 0; + SF_PDT_PARAM_CFG_S *pstparam = pfnParam->pstParam; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + while(i < SF_TTYUSB_RECV_MAX) + { + if(param->databuf[i] == 0x55 && param->databuf[i+1] == 0xAA) + break; + i++; + } + if(i > SF_TTYUSB_RECV_MAX) + return SF_DATA_ERROR_REQUEST; + pData = (UINT8*)param->databuf+i; + Temp = i; + + #if CS_DEBUG_INFO + MLOGD("[QUERYPENDING_PARAM] recv:\n"); + packet_log_printf(pData,(pstparam->ParaSync?50:200)); + #endif + + pData = (UINT8*)param->databuf+Temp+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; // 回复的登录指令 + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //payload len + result = *pData++; result = result<<8 | *pData++; //result + command = *pData++; command = command <<8 | *pData++; + + MLOGD("cmdID= 0x%x,len = 0x%x command = 0x%x,result = 0x%x \n",cmdID,len,command,result); + if(cmdID != 0x1009) + return SF_DATA_ERROR_REQUEST; + + + if(result != SF_SUCCESS) + return SF_DATA_ERROR_REQUEST; + + ; + switch(command) + { + case SF_CMD_QUERYPENDING_GETCFGFILE: + break; + + case SF_CMD_QUERYPENDING_GETPICTURE:/*get picture*/ + pStaticParam->stSubscribe.subscribeCnt = 1; + pStaticParam->stSubscribe.pSubscribe = malloc(sizeof(SF_SUBSCRIBE_ATTR_S)*pStaticParam->stSubscribe.subscribeCnt); + for(i = 0;istSubscribe.subscribeCnt;i++) + { + pStaticParam->stSubscribe.pSubscribe[i].subscribeType = *pData++; /*how to get pic */ + for(j=0;j<39;j++) /*filename*/ + pStaticParam->stSubscribe.pSubscribe[i].subscribeFileName[j] = *pData++; + MLOGD("SubscribeType:%d, SubscribeFileName:%s\n", + pStaticParam->stSubscribe.pSubscribe[i].subscribeType, + pStaticParam->stSubscribe.pSubscribe[i].subscribeFileName); + } + break; + + case SF_CMD_QUERYPENDING_GETSTATUS: + break; + + case SF_CMD_QUERYPENDING_GETSLEEPTIME: + break; + + case SF_CMD_QUERYPENDING_REBOOT: /*reboot*/ + break; + + case SF_CMD_QUERYPENDING_SETSYSTEMTIME: + break; + case SF_CMD_QUERYPENDING_GETCAMERAMODE: + break; + case SF_CMD_QUERYPENDING_SETCAMERAMODE: + pstparam->CamMode = (*pData++) - 1; + pstparam->ImgSize = (*pData++); + pstparam->Multishot = *pData++; + pstparam->Zoom = (*pData++) - 1; + pstparam->VideoSize = (*pData++) - 1; + pstparam->VideoLenth = *pData++; + pstparam->VideoFrame = *pData++; + pstparam->LightFreq = *pData++; + + MLOGD("CameraMode = [%d],ImgSize = [%d],Multishot = [%d],Zoom = [%d],\n " + "VideoSize = [%d],VideoLenth = [%d],VideoFrame = [%d],LightFreq = [%d]\n", + pstparam->CamMode, + pstparam->ImgSize, + pstparam->Multishot, + pstparam->Zoom, + pstparam->VideoSize, + pstparam->VideoLenth, + pstparam->VideoFrame, + pstparam->LightFreq); + break; + + case SF_CMD_QUERYPENDING_SETWORKMODE: + pstparam->TimelapseSwitch = *pData++; + pstparam->TimelapseTime.Hour = ((*pData++)-'0')*10; + pstparam->TimelapseTime.Hour += (*pData++)-'0'; + pstparam->TimelapseTime.Min = ((*pData++)-'0')*10; + pstparam->TimelapseTime.Min += (*pData++)-'0'; + pstparam->TimelapseTime.Sec = ((*pData++)-'0')*10; + pstparam->TimelapseTime.Sec += (*pData++)-'0'; + + temPir = *pData++; + + pstparam->DigitPirSensitivity = temPir; + if(pstparam->DigitPirSensitivity == 0) + pstparam->PirSwitch = 0; + else + pstparam->PirSwitch = 1; + + pstparam->PirSensitivity = sf_pir_to_digit_analog(pstparam->DigitPirSensitivity); + + pstparam->PirDelaySwitch = *pData++; + pstparam->PirDelayTime.Hour = ((*pData++)-'0')*10; + pstparam->PirDelayTime.Hour += (*pData++)-'0'; + pstparam->PirDelayTime.Min = ((*pData++)-'0')*10; + pstparam->PirDelayTime.Min += (*pData++)-'0'; + pstparam->PirDelayTime.Sec = ((*pData++)-'0')*10; + pstparam->PirDelayTime.Sec += (*pData++)-'0'; + + pstparam->WorkTime1Switch = *pData++; + pstparam->WorkTime[0].StartTime.Hour = ((*pData++)-'0')*10; + pstparam->WorkTime[0].StartTime.Hour += (*pData++)-'0'; + pstparam->WorkTime[0].StartTime.Min = ((*pData++)-'0')*10; + pstparam->WorkTime[0].StartTime.Min += (*pData++)-'0'; + pData++; + pstparam->WorkTime[0].StopTime.Hour = ((*pData++)-'0')*10; + pstparam->WorkTime[0].StopTime.Hour += (*pData++)-'0'; + pstparam->WorkTime[0].StopTime.Min = ((*pData++)-'0')*10; + pstparam->WorkTime[0].StopTime.Min += (*pData++)-'0'; + + pstparam->WorkTime2Switch = *pData++; + pstparam->WorkTime[1].StartTime.Hour = ((*pData++)-'0')*10; + pstparam->WorkTime[1].StartTime.Hour += (*pData++)-'0'; + pstparam->WorkTime[1].StartTime.Min = ((*pData++)-'0')*10; + pstparam->WorkTime[1].StartTime.Min += (*pData++)-'0'; + pData++; + pstparam->WorkTime[1].StopTime.Hour = ((*pData++)-'0')*10; + pstparam->WorkTime[1].StopTime.Hour += (*pData++)-'0'; + pstparam->WorkTime[1].StopTime.Min = ((*pData++)-'0')*10; + pstparam->WorkTime[1].StopTime.Min += (*pData++)-'0'; + + temPir = *pData++; + if(temPir == 0) + { + pstparam->PirSwitch = 0; + pstparam->DigitPirSensitivity = 0; + } + + pstparam->DailyReportswitch = *pData++; + pstparam->DailyReportTime.Hour = ((*pData++)-'0')*10; + pstparam->DailyReportTime.Hour += (*pData++)-'0'; + pstparam->DailyReportTime.Min = ((*pData++)-'0')*10; + pstparam->DailyReportTime.Min += (*pData++)-'0'; + + + pstparam->NightMode = *pData++; /*0: max 1: balance 2:Min*/ + pstparam->GprsMode = *pData++; /*0: trigger 1: all time*/ + pstparam->FlashLed = *pData++; /*0: all(default) 1: part*/ + pstparam->SendVideo = *pData++; /*0: no 1: yes*/ + pstparam->SendPhoto = *pData++; /*0: no 1: yes*/ + + pstparam->SendMultishot = *pData++; + if(pstparam->DailyReportswitch == 0) + { + if(pstparam->DailyReportTime.Hour == 0 && + pstparam->DailyReportTime.Min == 0) + { + pstparam->GprsMode = 1;/*realtime*/ + } + else + { + pstparam->GprsMode = 0;/*off*/ + } + } + else + { + + if((pstparam->DailyReportTime.Hour == 0) && (pstparam->DailyReportTime.Min == 30)) + { + pstparam->GprsMode = 2; + } + else if((pstparam->DailyReportTime.Hour == 1) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 3; + } + else if((pstparam->DailyReportTime.Hour == 2) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 4; + } + else if((pstparam->DailyReportTime.Hour == 3) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 5; + } + else if((pstparam->DailyReportTime.Hour == 4) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 6; + } + else if((pstparam->DailyReportTime.Hour == 6) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 7; + } + else if((pstparam->DailyReportTime.Hour == 12) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 8; + } + else if((pstparam->DailyReportTime.Hour == 24) && (pstparam->DailyReportTime.Min == 0)) + { + pstparam->GprsMode = 9; + } + } + + MLOGD("senmutilshot = [%d]\n", pstparam->SendMultishot); + MLOGD("pir = [%d-%d-%d]\n", pstparam->PirSwitch, pstparam->PirSensitivity, pstparam->DigitPirSensitivity); + MLOGD("timelapsepic = [%d,%02d:%02d:%02d]\n", pstparam->TimelapseSwitch, + pstparam->TimelapseTime.Hour, + pstparam->TimelapseTime.Min, + pstparam->TimelapseTime.Sec); + MLOGD("delaypic = [%d,%02d:%02d:%02d]\n", pstparam->PirDelaySwitch, + pstparam->PirDelayTime.Hour, + pstparam->PirDelayTime.Min, + pstparam->PirDelayTime.Sec); + MLOGD("dailypic = [%d,%02d:%02d:%02d]\n",pstparam->DailyReportswitch, + pstparam->DailyReportTime.Hour, + pstparam->DailyReportTime.Min, + pstparam->DailyReportTime.Sec); + MLOGD("WorkTime[0] = [%d,%02d:%02d-%02d:%02d]\n", pstparam->WorkTime1Switch, + pstparam->WorkTime[0].StartTime.Hour, + pstparam->WorkTime[0].StartTime.Min, + pstparam->WorkTime[0].StopTime.Hour, + pstparam->WorkTime[0].StopTime.Min); + MLOGD("WorkTime[1] = [%d,%02d:%02d-%02d:%02d]\n", pstparam->WorkTime2Switch, + pstparam->WorkTime[1].StartTime.Hour, + pstparam->WorkTime[1].StartTime.Min, + pstparam->WorkTime[1].StopTime.Hour, + pstparam->WorkTime[1].StopTime.Min); + + + + + break; + case SF_CMD_QUERYPENDING_SETOTHER: + pstparam->SendMaxNum = *pData++; //pstparam->MmsMax; + pData++; //pstparam->Tvout; + pData++; //pstparam->Audiorecord; + pstparam->StampSwitch = *pData++; //pstparam->Stamp; + pData++; //pstparam->Startuptone; + pData++; //pstparam->Keyboard; + pData++; //pstparam->CameraIDflag; + for(i=0;i<13;i++) + pData++; //pstparam->CameraID[i]; + pData++; //pstparam->CamerapasswdFlag; + for(i=0;i<6;i++) + pData++; //pstparam->Camerapasswd[i]; + + pstparam->SdLoop = *pData++; //pstparam->SDcycleRecord; + pData++ ;//pstparam->TriggerLogs; + pstparam->DateStyle = *pData++ ;//pstparam->DateStyle; + pstparam->GPSFlag = *pData++ ; + //pstparam->GPSFlag = 1 ; + for(i=0;i<21;i++) + pData++;//pstparam->GPSInfo[i]; + + MLOGD("SendMaxNum = [%d], StampSwitch = [%d], SdLoop = [%d] \n GPSFlag = [%d] DateStyle = [%d]\n", + pstparam->SendMaxNum, + pstparam->StampSwitch, + pstparam->SdLoop, + pstparam->GPSFlag, + pstparam->DateStyle); + + + pstparam->BatteryType = (*pData++) ; + MLOGD("battery = %d\n",pstparam->BatteryType); + break; + + case SF_CMD_QUERYPENDING_SETSERVER: + break; + + case SF_CMD_QUERYPENDING_UPLOADCFGFILE: + break; + + case SF_CMD_QUERYPENDING_GETMODECFG: + break; + + case SF_CMD_QUERYPENDING_GETOTHERCFG: + break; + + case SF_CMD_QUERYPENDING_GETSERVERPAREAM: + MLOGD("\n"); + break; + + case SF_CMD_QUERYPENDING_SETUPLOADPICSIZE: + break; + + case SF_CMD_QUERYPENDING_GETUPLOADPICSIZE: + break; + case SF_CMD_QUERYPENDING_SYNPARAM: + pstparam->ParaSync = *pData++; + MLOGD("ParaSync = [%d]\n", pstparam->ParaSync); + break; + + case SF_CMD_QUERYPENDING_VERSIONUPDATE: + break; + + case SF_CMD_QUERYPENDING_GETGPSINFO: + break; + + case SF_CMD_QUERYPENDING_SETGPSANTITHIEF: + pstparam->GPSAntitheftFlag = *pData++; + break; + case SF_QUERYPENDING_COMMAND_RESET: + pstparam->ResetFlag = *pData++; + break; + case SF_QUERYPENDING_COMMAND_FORMAT: + + pstparam->FormateFlag = *pData++; + + break; + default: + break; + + } + + return s16Ret; + +} + + +SINT32 sf_packetanalysis_trigger(SF_DATA_ATTR_S *param, SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + + UINT8 i = 0; + UINT8 Temp = 0; + UINT8 *pData = (UINT8*)param->databuf; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 cmdID = 0; + UINT16 result = 0; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + while(i < SF_TTYUSB_RECV_MAX) + { + if(param->databuf[i] == 0x55 && param->databuf[i+1] == 0xAA) + break; + i++; + } + if(i > SF_TTYUSB_RECV_MAX) + return SF_DATA_ERROR_REQUEST; + + pData = (UINT8*)param->databuf+i; + Temp = i; + + #if CS_DEBUG_INFO + MLOGD("[TRIGGER] recv:\n"); + packet_log_printf(pData,50); + #endif + + pData = (UINT8*)param->databuf+Temp+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; // 回复的指令 + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //负载长度 + result =*pData++; result = result<<8 | *pData++; //错误码 + + MLOGD("cmdID= 0x%x,len = 0x%x GetPicFlag = 0x%x \n",cmdID, len, result); + if(cmdID != 0x100d) + return SF_DATA_ERROR_REQUEST; +// if(result != 0) +// return SF_TCP_ERROR_UPLOAD_FILE_INFO; + pStaticParam->u8GetPicFlag = result; + + return SF_SUCCESS; + +} + +SINT32 sf_packetanalysis_bind_account(SF_DATA_ATTR_S *param,SF_FN_PARAM_S *pfnParam) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam,SF_FAILURE); + SF_COMM_CHECK_POINTER(pfnParam->pstaticParam,SF_FAILURE); + UINT8 i = 0; + UINT8 Temp = 0; + UINT8 *pData = (UINT8*)param->databuf; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 cmdID = 0; + UINT16 result = 0; + + SF_PDT_PARAM_STATISTICS_S *pStaticParam = pfnParam->pstaticParam; + + while(i < SF_TTYUSB_RECV_MAX) + { + if(param->databuf[i] == 0x55 && param->databuf[i+1] == 0xAA) + break; + i++; + } + if(i > SF_TTYUSB_RECV_MAX) + return SF_DATA_ERROR_REQUEST; + + pData = (UINT8*)param->databuf+i; + Temp = i; + + #if CS_DEBUG_INFO + MLOGD("[BIND_ACCOUNT] recv:\n"); + packet_log_printf(pData,50); + #endif + + pData = (UINT8*)param->databuf+Temp+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; // 回复的指令 + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //负载长度 + result =*pData++; result = result<<8 | *pData++; //reuslt + + MLOGD("cmdID= 0x%x,len = 0x%x result = 0x%x \n",cmdID, len, result); + if(cmdID != 0x100e) + return SF_DATA_ERROR_REQUEST; + + if(result != 0) + return SF_DATA_ERROR_FILE_SEND; + + pStaticParam->bindFlag = *pData++; + + for(i=0;i<50;i++) /*filename*/ + pStaticParam->BindAccount[i] = *pData++; + MLOGD("bindFlag:%d, BindAccount:%s\n", pStaticParam->bindFlag, pStaticParam->BindAccount); + + return SF_SUCCESS; + +} + + +SINT32 sf_packetanalysis_cmd_report(SF_DATA_ATTR_S *param) +{ + SF_COMM_CHECK_POINTER(param,SF_FAILURE); + SF_COMM_CHECK_POINTER(param->databuf,SF_FAILURE); + UINT8 i=0; + UINT8 Temp = 0; + UINT8 *pData = (UINT8*)param->databuf; + UINT16 seq = 0; + UINT16 len = 0; + UINT16 cmdID = 0; + UINT16 result = 0; + UINT16 command = 0; + + while(i < SF_TTYUSB_RECV_MAX) + { + if(param->databuf[i] == 0x55 && param->databuf[i+1] == 0xAA) + break; + i++; + } + + if(i > SF_TTYUSB_RECV_MAX) + return SF_DATA_ERROR_REQUEST; + + pData = (UINT8*)param->databuf+i; + Temp = i; + + #if CS_DEBUG_INFO + MLOGD("[REPORT_RESULT] recv:\n"); + packet_log_printf(pData,50); + #endif + + pData = (UINT8*)param->databuf+Temp+6; + + if(pData == SF_NULL) + return SF_DATA_ERROR_REQUEST; + + cmdID = *pData++; cmdID = cmdID <<8 | *pData++; // cam id + seq = *pData++; seq = seq <<8 | *pData++; + len = *pData++; len = len <<8 | *pData++; //payload len + result = *pData++; result = result<<8 | *pData++; //result + + MLOGD("cmdID= 0x%x,len = 0x%x result = 0x%x \n",cmdID,len,result); + if(cmdID != 0x100B) + return SF_DATA_ERROR_REQUEST; + + if(result != 0) + return SF_DATA_ERROR_REQUEST; + + command = *pData++; + command = command <<8 | *pData++; + + //MLOGD("command= 0x%x\n", command); + return SF_SUCCESS; + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + diff --git a/code/application/source/sf_app/code/source/debugMng/sf_debug.c b/code/application/source/sf_app/code/source/debugMng/sf_debug.c new file mode 100755 index 000000000..a4d5e84ac --- /dev/null +++ b/code/application/source/sf_app/code/source/debugMng/sf_debug.c @@ -0,0 +1,140 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" +#include "sf_debug.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +SINT8 bDebugEnble = SF_TRUE; +static SF_DEBUG_CMD_ATTR_S *stDebugCmdArray = SF_NULL; +static SINT16 DebugCmdArraylenth = 0; +SINT32 debug_cmd_parse(SF_CHAR *pString) +{ + SINT32 i = 0; + SINT32 index = 0; + SINT32 s32ret = 0; + SINT32 argc = 0; + SF_CHAR argv[8][32] = {0}; + SF_CHAR *pargv[8] = {0}; + SF_CHAR *pstr = 0; + + if(!stDebugCmdArray ||!DebugCmdArraylenth ) { + MLOGE("Debug have not created,please created before using it !!!!\n"); + return SF_FAILURE; + } + for(index = 0; index < DebugCmdArraylenth;index++) { + + if(strstr(pString, stDebugCmdArray[index].cmdStr)) + break; + } + + if(index >= DebugCmdArraylenth) { + MLOGE("[%s] not exist in cmd list",pString); + return SF_FAILURE; + } + + pstr = strtok(pString, " "); + while(pstr != SF_NULL) { + strcpy(argv[argc++],pstr); + + pstr = strtok(SF_NULL, " "); + } + + for(i = 0; i < argc && argc < 8 ;i++) { + pargv[i] = &argv[i][0]; + } + + if(!stDebugCmdArray[index].pfn_debug_cmd_exe){ + MLOGE("cmd [%s] undefineed cmd exe function !!!\n",stDebugCmdArray[index].cmdStr); + return SF_FAILURE; + } + + s32ret = stDebugCmdArray[index].pfn_debug_cmd_exe(argc,pargv); + + return s32ret; + +} +SINT32 sf_debug_init(SF_CHAR *filepath,SINT32 *fd) +{ + SINT32 s32ret = SF_SUCCESS; + s32ret = mkfifo(filepath, 0777); + + *fd = open(filepath,O_RDWR); + if(*fd < 0) { + MLOGE("open [%s] failed !!!\n",filepath); + return SF_FAILURE; + } + return s32ret; +} +SINT32 sf_debug_create(SF_DEBUG_CMD_ATTR_S *pDebugCmdArray,SINT16 lenth) +{ + stDebugCmdArray=pDebugCmdArray; + DebugCmdArraylenth = lenth; + return SF_SUCCESS; +} + +SINT32 sf_debug_start(SINT32 fd) +{ + SINT32 s32ret = SF_SUCCESS; + fd_set read_fds; + SF_CHAR fifo_data[256] = {0}; + + while (bDebugEnble) { + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + s32ret = select(fd + 1, &read_fds, NULL, NULL, NULL); + if (s32ret > 0) { + if (FD_ISSET(fd, &read_fds)) { + s32ret = read(fd, fifo_data, 256); + if (s32ret > 0) { + debug_cmd_parse(fifo_data); + memset(fifo_data, 0x00, 256); + } + } + FD_CLR(fd, &read_fds); + } + else if (s32ret < 0) { + MLOGE("FIFO select failed\n"); + continue; + } + else if (0 == s32ret) { + MLOGW("FIFO select timeout\n"); + continue; + } + } + return SF_SUCCESS; +} +SINT32 sf_debug_stop(void) +{ + bDebugEnble = SF_FALSE; + return SF_SUCCESS; +} + +SINT32 sf_debug_deinit(SINT32 fd) +{ + return close(fd); +} + + + diff --git a/code/application/source/sf_app/code/source/devMng/sf_dev_other.c b/code/application/source/sf_app/code/source/devMng/sf_dev_other.c new file mode 100755 index 000000000..ce07ca6ac --- /dev/null +++ b/code/application/source/sf_app/code/source/devMng/sf_dev_other.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include "sf_log.h" +#include "sf_ledmng.h" +#include "sf_hal_gpio.h" +#include "sf_systemMng.h" +#include "sf_message_queue.h" + + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +extern pthread_mutex_t GPIO_mutexLock; + +SINT32 sf_dev_pir_status_get(void) +{ + SINT8 regValue = 0; + SF_MUTEX_LOCK(GPIO_mutexLock); + sf_hal_gpio_get(GPIOID_PIR_TEST, ®Value); + SF_MUTEX_UNLOCK(GPIO_mutexLock); + return (regValue & 0xFF)?1:0; +} +UINT16 sf_pir_to_digit_analog(UINT8 pirs) + { + UINT16 pirlevel = 0; + + if(pirs > 7) + pirlevel = 0; + else if(pirs > 6) + pirlevel = 1; + else + pirlevel = 2; + + return pirlevel; + } + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/devMng/sf_dev_usb.c b/code/application/source/sf_app/code/source/devMng/sf_dev_usb.c new file mode 100755 index 000000000..71114e6e7 --- /dev/null +++ b/code/application/source/sf_app/code/source/devMng/sf_dev_usb.c @@ -0,0 +1,45 @@ +#include +#include +#include + +#include "sf_dev_usb.h" +static UINT8 usb_app_mode = SF_USB_APP_CHARGE; +extern pthread_mutex_t GPIO_mutexLock; + +void sf_usb_app_mode_set(SF_USB_MODE_E mode) +{ + usb_app_mode = mode; +} + +SF_USB_MODE_E sf_usb_app_mode_get(void) +{ + return usb_app_mode; +} + +SINT32 sf_usb_IsInsert(void) +{ + SINT8 regValue = 0; + SF_MUTEX_LOCK(GPIO_mutexLock); + sf_hal_gpio_init(GPIOID_USB_INSERT, GPIO_DIR_IN); + sf_hal_gpio_get(GPIOID_USB_INSERT, ®Value); + sf_hal_gpio_deinit(GPIOID_USB_INSERT); + SF_MUTEX_UNLOCK(GPIO_mutexLock); + + return (regValue & 0xFF) ? 1:0; +} + + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/devMng/sf_keymng.c b/code/application/source/sf_app/code/source/devMng/sf_keymng.c new file mode 100755 index 000000000..76dada235 --- /dev/null +++ b/code/application/source/sf_app/code/source/devMng/sf_keymng.c @@ -0,0 +1,231 @@ +#include +#include +#include +#include + +#include "sf_log.h" +#include "sf_systemMng.h" +#include "sf_dev_usb.h" +#include "sf_module.h" + +#include "sf_message_queue.h" +#include "sf_keymng.h" + + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define SF_KEY_COUNT_MAX 4 +#define SF_KEY_HOLDCNT_MAX 16 +#define SF_KEY_LONGCNT_MAX 250 +#define SF_SYNC_KEY_LONGCNT_MAX 150 +extern pthread_mutex_t GPIO_mutexLock; + +SF_KEYMNG_INFO_S stKeyTable[SF_KEY_COUNT_MAX] = { + {SF_KEY_PIN_SYNC, 1, 0, SF_SYNC_KEY_LONGCNT_MAX, SF_KEY_STATE_UP}, + {SF_KEY_PIN_FORMAT, 1, 0, SF_KEY_LONGCNT_MAX, SF_KEY_STATE_UP}, + {SF_KEY_PIN_RESET, 1, 0, SF_KEY_LONGCNT_MAX, SF_KEY_STATE_UP}, + {SF_KEY_PIN_DATAREADY, 0, 0, SF_KEY_LONGCNT_MAX, SF_KEY_STATE_UP}, + }; + +SF_THREAD_S sf_keyctrl = +{ + .IsRun = 0, + .TskId = -1, +}; + + +SINT32 Keyctrl_status_get(U32 gpio_num,SINT8 u32status,SF_KEY_STATE_E* penKeyState ) +{ + SINT8 halvalue = 0; + SF_MUTEX_LOCK(GPIO_mutexLock); + sf_hal_gpio_get(gpio_num,&halvalue); + SF_MUTEX_UNLOCK(GPIO_mutexLock); + //MLOGI("[%d,%d,%d]\n",gpio_num,u32status,halvalue); + *penKeyState = (u32status == halvalue)?SF_KEY_STATE_UP:SF_KEY_STATE_DOWN; + return SF_SUCCESS; +} + +static SINT32 Keyctrl_clickcheck(SF_KEYMNG_INFO_S *pstKeyTable) +{ + SF_KEY_STATE_E enKeyState = SF_KEY_STATE_UP; + SF_MESSAGE_BUF_S stMessageBuf = {0}; + + Keyctrl_status_get(pstKeyTable->u8keyIdx,pstKeyTable->u32status,&enKeyState); + + if(enKeyState == SF_KEY_STATE_DOWN) { + if(pstKeyTable->enState == SF_KEY_STATE_UP) { + + pstKeyTable->enState = SF_KEY_STATE_DOWN; + + stMessageBuf.cmdId = CMD_KEY; + stMessageBuf.arg1 = SF_EVENT_KEY_HOLD_DOWN; + stMessageBuf.arg2 = pstKeyTable->u8keyIdx; + + sf_com_message_send_to_app(&stMessageBuf); + } + if (pstKeyTable->u32keycount < pstKeyTable->ShortLongMaxCount) { + pstKeyTable->u32keycount++; + if (pstKeyTable->u32keycount >= pstKeyTable->ShortLongMaxCount)///long press + { + stMessageBuf.cmdId = CMD_KEY; + stMessageBuf.arg1 = SF_EVENT_KEY_LONG_CLICK; + stMessageBuf.arg2 = pstKeyTable->u8keyIdx; + sf_com_message_send_to_app(&stMessageBuf); + } + } + } + else { + if(pstKeyTable->enState == SF_KEY_STATE_DOWN) { + + pstKeyTable->enState = SF_KEY_STATE_UP; + stMessageBuf.cmdId = CMD_KEY; + stMessageBuf.arg1 = SF_EVENT_KEY_HOLD_UP; + stMessageBuf.arg2 = pstKeyTable->u8keyIdx; + + sf_com_message_send_to_app(&stMessageBuf); +// if (pstKeyTable->u32keycount >= pstKeyTable->ShortLongMaxCount)///long press +// { +// stMessageBuf.cmdId = CMD_KEY; +// stMessageBuf.arg1 = SF_EVENT_KEY_LONG_CLICK; +// stMessageBuf.arg2 = pstKeyTable->u8keyIdx; +// sf_com_message_send_to_app(&stMessageBuf); +// } + + if (pstKeyTable->u32keycount < pstKeyTable->ShortLongMaxCount) + { + stMessageBuf.cmdId = CMD_KEY; + stMessageBuf.arg1 = SF_EVENT_KEY_SHORT_CLICK; + stMessageBuf.arg2 = pstKeyTable->u8keyIdx; + sf_com_message_send_to_app(&stMessageBuf); + } + pstKeyTable->u32keycount = 0; + } + } + return SF_SUCCESS; + +} + +void* Keyctrl_thread(void *argv) +{ + SINT8 i = 0; + while (sf_keyctrl.IsRun) + { + + if(sf_usb_app_mode_get() != SF_USB_APP_CHARGE ||sf_4G_status_get() != SF_4G_FREE /*|| */) + continue; + if(sf_poweron_type_get() != SF_MCU_STARTUP_ONKEY) + i = 3; + + Keyctrl_clickcheck(&stKeyTable[i]); + + i++; + if(i>= SF_KEY_COUNT_MAX) + i = 0; + + usleep(5000); + } + pthread_exit(NULL); +} +const SF_CHAR* sf_keyctrl_getstatusstring(SF_MESSAGE_CMD_KEY_E enType) +{ + switch(enType) + { + case SF_EVENT_KEY_SHORT_CLICK: + return "SF_EVENT_KEY_SHORT_CLICK"; + case SF_EVENT_KEY_LONG_CLICK: + return "SF_EVENT_KEY_LONG_CLICK"; + case SF_EVENT_KEY_HOLD_DOWN: + return "SF_EVENT_KEY_HOLD_DOWN"; + case SF_EVENT_KEY_HOLD_UP: + return "SF_EVENT_KEY_HOLD_UP"; + case SF_EVENT_KEY_GROUP: + return "SF_EVENT_KEY_GROUP"; + default: + return "Unknown"; + } +} +const SF_CHAR* sf_keypin_getstatusstring(SF_KEY_PIN_E enType) +{ + switch(enType) + { + case SF_KEY_PIN_RESET: + return "SF_KEY_PIN_RESET"; + case SF_KEY_PIN_SYNC: + return "SF_KEY_PIN_SYNC"; + case SF_KEY_PIN_FORMAT: + return "SF_KEY_PIN_FORMAT"; + case SF_KEY_PIN_DATAREADY: + return "SF_KEY_PIN_DATAREADY"; + case SF_KEY_PIN_FILESTATUS: + return "SF_KEY_PIN_FILESTATUS"; + default: + return "Unknown"; + } +} + +SINT32 sf_Key_ctrl_init(void) +{ + SINT8 i = 0; + MLOGI("\n"); + for(i=0;i +#include +#include + +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" + +#include "sf_module.h" +#include "sf_ledmng.h" +#include "sf_hal_gpio.h" +#include "sf_systemMng.h" +#include "sf_storeMng.h" + +#include "sf_message_queue.h" +#include "sf_hal_ttyusb.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +SF_LED_EVENT_S stLedEevntgroup= {0}; +const SF_CHAR* sf_led_status_getstatusstring(SF_LED_STATUS_E enType) +{ + switch(enType) + { + case LED_STATUS_HOLD_OFF: + return "LED_STATUS_HOLD_OFF"; + + case LED_STATUS_HOLD_ON: + return "LED_STATUS_HOLD_ON"; + + case LED_STATUS_SLOWFLASH_ON: + return "LED_STATUS_SLOWFLASH_ON"; + + case LED_STATUS_QUICKFLASH_ON: + return "LED_STATUS_QUICKFLASH_ON"; + + case LED_STATUS_FLASH_OFF: + return "LED_STATUS_FLASH_OFF"; + + default: + return "Unknown"; + } +} +const SF_CHAR* sf_led_type_getstatusstring(SF_LED_TYPE_E enType) +{ + switch(enType) + { + case LED_TYPE_OFF: + return "LED_TYPE_OFF"; + case LED_TYPE_GREEN: + return "LED_TYPE_GREEN"; + case LED_TYPE_YELLOW: + return "LED_TYPE_YELLOW"; + case LED_TYPE_RED: + return "LED_TYPE_RED"; + case LED_TYPE_ON: + return "LED_TYPE_ON"; + default: + return "Unknown"; + } +} +const SF_CHAR* sf_led_group_getstatusstring(SF_LED_GROUD_E enType) +{ + switch(enType) + { + case LED_GROUP_SD: + return "LED_GROUP_SD"; + case LED_GROUP_BAT: + return "LED_GROUP_BAT"; + case LED_GROUP_SIGNAL: + return "LED_GROUP_SIGNAL"; + case LED_GROUP_ACCOUNT: + return "LED_GROUP_ACCOUNT"; + case LED_GROUP_STATUS: + return "LED_GROUP_STATUS"; + default: + return "Unknown"; + } +} + +SINT32 sf_led_add_exe(SF_LED_EVENT_CALLBACK_FN_PTR pfn_led_event_exe) +{ + SF_MUTEX_INIT_LOCK(stLedEevntgroup.LEDMNGMutex); + stLedEevntgroup.pfn_led_event_exe = pfn_led_event_exe; + return SF_SUCCESS; +} +SINT32 sf_led_remove_exe(SF_LED_EVENT_CALLBACK_FN_PTR pfn_led_event_exe) +{ + stLedEevntgroup.pfn_led_event_exe = SF_NULL; + return SF_SUCCESS; +} + +SINT32 sf_led_event_register(SINT8 enLedEvent) +{ + SINT32 eventID = 0; + if(stLedEevntgroup.pfn_led_event_exe == SF_NULL) { + MLOGE("please register exe !!!\n"); + return SF_FAILURE; + } + + for(eventID = 0;eventID < LED_GRPOUP_MAX ; eventID++) { + if(stLedEevntgroup.stLedGroupReg[eventID].IsUsed == 0) { + stLedEevntgroup.stLedGroupReg[eventID].LedGroupID = enLedEvent; + stLedEevntgroup.stLedGroupReg[eventID].IsUsed = 1; + break; + } + else { + if(stLedEevntgroup.stLedGroupReg[eventID].LedGroupID == enLedEvent ) { + MLOGE("event [%d] [%d] registered !!!\n",enLedEvent,eventID); + } + } + } + if(eventID >= LED_GRPOUP_MAX) { + MLOGE("event lenth too large ,mare than 100!!!\n"); + return SF_FAILURE; + } + return SF_SUCCESS; +} + +SINT32 sf_led_event_unregister(SINT8 enLedEvent) +{ + SINT32 eventID = 0; + for(eventID = 0;eventID < LED_GRPOUP_MAX ; eventID++) { + stLedEevntgroup.stLedGroupReg[eventID].IsUsed = 0; + stLedEevntgroup.stLedGroupReg[eventID].LedGroupID =0; + } + return SF_SUCCESS; +} + +void* led_flash_thread(void* pData) +{ + SF_LED_REG_S *pLedFlashCfg = (SF_LED_REG_S*)pData; + + while(pLedFlashCfg->IsRun) + { + SF_MUTEX_LOCK(stLedEevntgroup.LEDMNGMutex); + stLedEevntgroup.pfn_led_event_exe(pLedFlashCfg->LedGroupID,pLedFlashCfg->enStatusType); + SF_MUTEX_UNLOCK(stLedEevntgroup.LEDMNGMutex); + + sf_sleep_ms(pLedFlashCfg->FlashTimeUs); + + SF_MUTEX_LOCK(stLedEevntgroup.LEDMNGMutex); + stLedEevntgroup.pfn_led_event_exe(pLedFlashCfg->LedGroupID,LED_TYPE_OFF); + SF_MUTEX_UNLOCK(stLedEevntgroup.LEDMNGMutex); + + sf_sleep_ms(pLedFlashCfg->FlashTimeUs); + + } + + return NULL; +} +SINT32 sf_led_flash_start(SF_LED_REG_S *pLedGroupReg) +{ + SINT32 ret = 0; + + pLedGroupReg->IsRun = 1; + ret = pthread_create(&(pLedGroupReg->TskId), NULL, led_flash_thread, (void*)pLedGroupReg); + if(ret != SF_SUCCESS) { + pLedGroupReg->IsRun = 0; + MLOGE("Create pthread fail !!\n"); + return SF_FAILURE; + } + return SF_SUCCESS; +} +SINT32 sf_led_flash_stop(SF_LED_GROUD_E enLedGroupType) +{ + SINT32 s32ret = SF_SUCCESS; + + if(stLedEevntgroup.stLedGroupReg[enLedGroupType].IsRun == 0) { +// MLOGW("thread have already stop !!!\n"); + return SF_FAILURE; + } + stLedEevntgroup.stLedGroupReg[enLedGroupType].IsRun = 0; + s32ret = pthread_join(stLedEevntgroup.stLedGroupReg[enLedGroupType].TskId, NULL); + if(s32ret != SF_SUCCESS) + { + MLOGD("thread stop fail!\n"); + return s32ret; + } + + return SF_SUCCESS; +} +SINT32 sf_led_event_process(SINT32 arg1,SINT32 arg2,SINT32 arg3) +{ + SINT32 eventID = 0; +// MLOGI("ARG1:%d,ARG2:%d,ARG3:%d\n",arg1,arg2,arg3); + sf_led_flash_stop(arg2); + + switch(arg1) + { + case LED_STATUS_HOLD_OFF: + case LED_STATUS_HOLD_ON: + SF_MUTEX_LOCK(stLedEevntgroup.LEDMNGMutex); + stLedEevntgroup.pfn_led_event_exe(arg2,arg3); + SF_MUTEX_UNLOCK(stLedEevntgroup.LEDMNGMutex); + break; + case LED_STATUS_SLOWFLASH_ON: + case LED_STATUS_QUICKFLASH_ON: + for(eventID = 0;eventID < LED_GROUP_BUIT ; eventID++) { + if(stLedEevntgroup.stLedGroupReg[eventID].LedGroupID == arg2 \ + && stLedEevntgroup.stLedGroupReg[eventID].IsUsed == 1) { + + stLedEevntgroup.stLedGroupReg[eventID].enStatusType = arg3; + stLedEevntgroup.stLedGroupReg[eventID].FlashTimeUs = (arg1 == LED_STATUS_SLOWFLASH_ON)?500:250; + break; + } + } + if(eventID >= LED_GROUP_BUIT) { + MLOGE("%d,have not been registered!!!\n",arg2); + return SF_FAILURE; + } + + sf_led_flash_start(&stLedEevntgroup.stLedGroupReg[eventID]); + break; + default: + MLOGE("led group [%d] existed Unknown param [%d]\n",arg2,arg1); + return SF_FAILURE; + break; + } + return SF_SUCCESS; +} + + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/fileMng/cJSON.c b/code/application/source/sf_app/code/source/fileMng/cJSON.c new file mode 100755 index 000000000..2495f067c --- /dev/null +++ b/code/application/source/sf_app/code/source/fileMng/cJSON.c @@ -0,0 +1,2953 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" +#include "sf_log.h" + +/* define our own boolean type */ +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { + if (!cJSON_IsString(item)) { + return NULL; + } + + return item->valuestring; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 1) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(*allocate)(size_t size); + void (*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ +static void *internal_malloc(size_t size) +{ + return malloc(size); +} +static void internal_free(void *pointer) +{ + free(pointer); +} +static void *internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + SINT32 number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valueSINT32 = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or SINT32 */ +CJSON_PUBLIC(SINT32) cJSON_SetNumberHelper(cJSON *object, SINT32 number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valueSINT32 = number; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) + { + memcpy(newbuffer, p->buffer, p->offset + 1); + } + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + SINT32 d = item->valueSINT32; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + SINT32 test; + + if (output_buffer == NULL) + { + return false; + } + //printf("Json->num = %d\n", d); + /* This checks for NaN and Infinity */ + if ((d * 0) != 0) + { + length = sprintf((char*)number_buffer, "null"); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%d", d); + //printf("d length=%d\n",length); + //printf("json->numStr = _%s_\n", number_buffer); + #if 1 + /* Check whether the original SINT32 can be recovered */ + if ((sscanf((char*)number_buffer, "%d", &test) != 1) || ((SINT32)test != d)) + { + /* If not, print with 17 decimal places of precision */ + // printf("number_buffer error \n"); + length = sprintf((char*)number_buffer, "%d", d); + } + #endif + } + //printf("json->numStr = _%s_\n", number_buffer); + /* sprintf failed or buffer overrun occured */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = strlen((const char*)value) + sizeof(""); + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +#define cjson_min(a, b) ((a < b) ? a : b) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + buffer->buffer = NULL; + if (printed == NULL) { + goto fail; + } + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) + { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((len < 0) || (buf == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buf; + p.length = (size_t)len; + p.offset = 0; + p.noalloc = true; + p.format = fmt; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + if (!output_buffer->noalloc) + { + output_buffer->hooks.deallocate(output_buffer->buffer); + } + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* faile to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL)) + { + return false; + } + + child = array->child; + + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + } + else + { + /* append to the end */ + while (child->next) + { + child = child->next; + } + suffix_object(child, item); + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + if ((object == NULL) || (string == NULL) || (item == NULL)) + { + return false; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + if (constant_key) + { + item->string = (char*)cast_away_const(string); + item->type |= cJSON_StringIsConst; + } + else + { + //printf("string = %s,", string); + char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (key == NULL) + { + return false; + } + + item->string = key; + item->type &= ~cJSON_StringIsConst; + } + //printf("item num = %d\n", item->valueSINT32); + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return; + } + + add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return; + } + + add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const SINT32 number) +{ + + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + //printf("item add to object fail!\n"); + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item->prev != NULL) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) + { + return; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + add_item_to_array(array, newitem); + return; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (parent->child == item) + { + parent->child = replacement; + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return; + } + + cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = b ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(SINT32 num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valueSINT32 = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((SINT32)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateSINT32Array(const SINT32 *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0;a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valueSINT32 = item->valueSINT32; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + unsigned char *into = (unsigned char*)json; + + if (json == NULL) + { + return; + } + + while (*json) + { + if (*json == ' ') + { + json++; + } + else if (*json == '\t') + { + /* Whitespace characters. */ + json++; + } + else if (*json == '\r') + { + json++; + } + else if (*json=='\n') + { + json++; + } + else if ((*json == '/') && (json[1] == '/')) + { + /* SINT32-slash comments, to end of line. */ + while (*json && (*json != '\n')) + { + json++; + } + } + else if ((*json == '/') && (json[1] == '*')) + { + /* multiline comments. */ + while (*json && !((*json == '*') && (json[1] == '/'))) + { + json++; + } + json += 2; + } + else if (*json == '\"') + { + /* string literals, which are \" sensitive. */ + *into++ = (unsigned char)*json++; + while (*json && (*json != '\"')) + { + if (*json == '\\') + { + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + else + { + /* All other characters. */ + *into++ = (unsigned char)*json++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (a->valueSINT32 == b->valueSINT32) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} + +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/fileMng/sf_fileMng.c b/code/application/source/sf_app/code/source/fileMng/sf_fileMng.c new file mode 100755 index 000000000..0554f4ab0 --- /dev/null +++ b/code/application/source/sf_app/code/source/fileMng/sf_fileMng.c @@ -0,0 +1,664 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sf_log.h" +#include "sf_fileMng.h" +#include "HMACSHA.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +SF_SRCFILE_ATTR_S *pThumbFileCfg = 0; + +//"^HRT[0-9]{5}.txt$" +//"^W[0-9]{7}.txt$" + +//"^(W|HRT)[0-9]{5,7}.txt$" + + + + + +SINT32 sf_file_IsExsit(CHAR *fileName) +{ + return (access((char*)fileName, F_OK) == 0)?SF_TRUE:SF_FALSE; +} +SINT32 sf_file_remove(SF_CHAR *fileName) +{ + SINT8 count = 0; + SF_CHAR cmdstring[64] = {0}; + SINT32 s32ret = SF_SUCCESS; + do { + MLOGI("removing [%s]\n",fileName); + sprintf(cmdstring,"rm -rf %s",fileName); + s32ret = system(cmdstring); + sync(); + + if(s32ret != SF_SUCCESS) + { + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = 0x0113; + stMessageBuf.arg1 = 0; + sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + } + count++; + }while(sf_file_IsExsit((CHAR *)fileName) == SF_TRUE && count < 10); + + if(sf_file_IsExsit((CHAR *)fileName) != SF_TRUE) + MLOGI("removed [%s]\n",fileName); + if(count >= 10) + { + MLOGE("remove [%s] failed !!!\n",fileName); + return SF_FAILURE; + } + return SF_SUCCESS; +} + +SINT32 sf_file_size_get(SF_CHAR *filePath,UINT32 *pFileSize) +{ + SF_COMM_CHECK_POINTER(filePath,SF_FAILURE); + + SINT32 fd = 0; + struct stat statBuf; + + fd = open(filePath, O_RDWR); /*open jpg file*/ + if(fd < 0) { +// MLOGE("open [%s] failed !!!,errno = [%d,%s]\n",filePath,errno,strerror(errno)); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = 0x0113; + stMessageBuf.arg1 = 0; + sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + fd = open(filePath, O_RDWR); /*open jpg file*/ + if(fd < 0) { + MLOGE("open [%s] failed !!!,errno = [%d,%s]\n",filePath,errno,strerror(errno)); + return SF_FAILURE; + } + } + + + fstat(fd, &statBuf); + *pFileSize = statBuf.st_size; + + close(fd); + + return SF_SUCCESS; +} + + + +SINT32 sf_file_txt_fill(SF_FILE_ATTR_S *pstFileAttr) +{ + SF_COMM_CHECK_POINTER(pstFileAttr->thumbfilePath,SF_FAILURE); + SF_COMM_CHECK_POINTER(pstFileAttr->txtfilePath,SF_FAILURE); + + SINT32 len = 0; + SF_CHAR *pBuf = NULL; + SF_CHAR *bufBak = NULL; + UINT32 readSize = 0; + UINT32 tolFileSize = 0; + SINT32 fdScrFile = 0; + SINT32 fdDstFile = 0; + + + fdScrFile = open(pstFileAttr->thumbfilePath, O_RDWR); /*open jpg file*/ + SF_APPCOMM_CHECK_OPENFILE_RETURN(fdScrFile,pstFileAttr->thumbfilePath, SF_FAILURE); + + + fdDstFile = open(pstFileAttr->txtfilePath, O_RDWR); /*open txt file*/ + SF_APPCOMM_CHECK_OPENFILE_RETURN(fdDstFile,pstFileAttr->txtfilePath, SF_FAILURE); + + tolFileSize = pstFileAttr->thumbfileSize; + + MLOGD("tolFileSize = %d\n",tolFileSize); + MLOGD("thumbfilePath = %s\n",pstFileAttr->thumbfilePath); + MLOGD("txtfilePathName = %s\n",pstFileAttr->txtfilePath); + + + bufBak = (tolFileSize > MMZBLOCKSIZE)?(SF_CHAR*)malloc(MMZBLOCKSIZE):(SF_CHAR*)malloc(tolFileSize); + if(bufBak < 0) + { + MLOGE("malloc buf fail!\n"); + close(fdScrFile); + close(fdDstFile); + return SF_FAILURE; + + } + + lseek(fdDstFile, 0, SEEK_END); + while(tolFileSize > 0) + { + pBuf = bufBak; + readSize = (tolFileSize >= MMZBLOCKSIZE)?read(fdScrFile, pBuf, MMZBLOCKSIZE):read(fdScrFile, pBuf, tolFileSize); + if(readSize<= 0) + { + + MLOGE("read fail!\n"); + free(bufBak); + close(fdScrFile); + close(fdDstFile); + return SF_FAILURE; + } + + + tolFileSize -= readSize; + len = write(fdDstFile, pBuf, readSize); + + if (len != readSize) + { + MLOGE("write fail!\n"); + free(bufBak); + close(fdScrFile); + close(fdDstFile); + return SF_FAILURE; + } + } + + free(bufBak); + close(fdScrFile); + close(fdDstFile); + return SF_SUCCESS; + +} + +#if defined(CFG_TRANSDATA_AT) +SINT32 sf_file_http_header_add(SF_FILE_ATTR_S *pstFileAttr, SF_PDT_PARAM_STATISTICS_S *pStaticParam) +{ + SF_COMM_CHECK_POINTER(pstFileAttr,SF_FAILURE); + SF_COMM_CHECK_POINTER(pStaticParam,SF_FAILURE); + + SINT32 s32Ret = SF_SUCCESS; + SINT16 i = 0; + SINT16 fd = 0; + SF_CHAR typestr[16] = {0}; + SF_CHAR httpstr[512] = {0}; + SF_CHAR objectName[128] = {0}; + SF_CHAR txtfilename[64] = {0}; + SF_CHAR txtfilePathName[128] = {0}; + SF_CHAR picfilename[36] = {0};//src jpg file + SF_CHAR amzPw[128] = {0}; + SF_CHAR signatureStr[128] = {0}; + + MLOGD("sf_http_header: B\n"); + MLOGD("pstFileAttr->enFileTye:%d\n", pstFileAttr->enFileTye); + MLOGD("pstFileAttr->thumbfileName:%s,%d\n", pstFileAttr->thumbfileName, strlen(pstFileAttr->thumbfileName)); + + if(pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_SMALL) + sprintf(objectName,"%s/thumb_%s", pStaticParam->IMEI, pstFileAttr->thumbfileName); + else + sprintf(objectName,"%s/%s", pStaticParam->IMEI, pstFileAttr->thumbfileName); + + memcpy(picfilename, pstFileAttr->thumbfileName, strlen(pstFileAttr->thumbfileName)-4); + sprintf(txtfilename, "%s.txt", picfilename);/*creat txt file name*/ + sprintf(txtfilePathName, "%s%s", SF_SD_ROOT, txtfilename); /*creat txt file path*/ + + MLOGD("txtfilePathName =[%s]\n",txtfilePathName); + MLOGD("thumbfilePath =[%s]\n",pstFileAttr->thumbfilePath); + s32Ret = sf_file_size_get(pstFileAttr->thumbfilePath,&pstFileAttr->thumbfileSize); + if(pstFileAttr->thumbfileSize < 0 ||s32Ret == SF_FAILURE) + { + MLOGE("thumbfilePath%s]: filesize error\n", pstFileAttr->thumbfilePath); + return SF_FAILURE; + } + + fd = open(txtfilePathName, O_CREAT|O_RDWR, 0); + if(fd <= 0) + { + MLOGE("create file [%s] failed\n",txtfilePathName); + return SF_FAILURE; + } + + if(pstFileAttr->enFileTye < SF_FILE_TYPE_VIDEO) + sprintf(typestr,"image/JPG"); + else if(pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO) + sprintf(typestr,"video/MOV"); + else if(pstFileAttr->enFileTye == SF_FILE_TYPE_GPS) + sprintf(typestr,"text/plain"); + + for(i=0;i<7;i++) + { + memset(httpstr, '\0', sizeof(httpstr)); + switch(i) + { + case 0: + sprintf(httpstr, "PUT /%s HTTP/1.1\r\n", objectName); + break; + case 1: + sprintf(httpstr, "Host: %s.%s\r\n", pStaticParam->stOssCfg.szBucket, AMZ_HOST);//s3 + break; + case 2: + sprintf(amzPw,"%s%s", AMZ_PW_TITLE, pStaticParam->stOssCfg.szPassword); + amz_signature((UINT8*)signatureStr,pstFileAttr->thumbfileSize,(UINT8*)objectName,(UINT8*)typestr,(UINT8*)amzPw,pStaticParam->stOssCfg.szBucket,pStaticParam->stOssCfg.szIP); + sprintf(httpstr,"Authorization: %s Credential=%s/%d%02d%02d/%s/%s/%s,SignedHeaders=content-length;content-type;host;x-amz-date,Signature=%s\r\n", + SECRET_TYPE, + pStaticParam->stOssCfg.szUsername, + pStaticParam->httpTime.Year, + pStaticParam->httpTime.Mon, + pStaticParam->httpTime.Day, + pStaticParam->stOssCfg.szIP, + AMZ, + SECRET_VER, + signatureStr); + + break; + case 3: + sprintf(httpstr,"Content-Length: %d\r\n",pstFileAttr->thumbfileSize); + break; + case 4: + sprintf(httpstr,"Content-Type: %s\r\n",typestr); + break; + case 5: + sprintf(httpstr,"x-amz-date: %d%02d%02dT%02d%02d%02dZ\r\n", + pStaticParam->httpTime.Year, + pStaticParam->httpTime.Mon, + pStaticParam->httpTime.Day, + pStaticParam->httpTime.Hour, + pStaticParam->httpTime.Min, + pStaticParam->httpTime.Sec); + + break; + case 6: + sprintf(httpstr,"x-amz-content-sha256: UNSIGNED-PAYLOAD\r\n\r\n"); + break; + } + + write(fd, httpstr, strlen(httpstr)); + + } + close(fd); + memcpy(pstFileAttr->txtfileName, txtfilename, strlen(txtfilename)); + memcpy(pstFileAttr->txtfilePath, txtfilePathName, strlen(txtfilePathName)); + + return s32Ret; +} + +SINT32 sf_file_subscribe_check(SF_FILE_ATTR_S *pstfileAttr, SF_SUBSCRIBE_ATTR_S *pSubscribe) +{ + SF_COMM_CHECK_POINTER(pstfileAttr,SF_FAILURE); + SF_COMM_CHECK_POINTER(pSubscribe,SF_FAILURE); + + UINT16 dirKey = 0; + UINT16 fileKey = 0; + + SINT32 ret = 0; + SF_CHAR tempStr[6] = {0}; + SF_CHAR fileName[16] = {0}; + SF_CHAR filePath[128] = {0}; + + memset(pstfileAttr->thumbfileName, '\0', sizeof(pstfileAttr->thumbfileName)); + memset(pstfileAttr->thumbfilePath, '\0', sizeof(pstfileAttr->thumbfilePath)); + memset(pstfileAttr->txtfileName, '\0', sizeof(pstfileAttr->txtfileName)); + memset(pstfileAttr->txtfilePath, '\0', sizeof(pstfileAttr->txtfilePath)); + + + switch(pSubscribe->subscribeType) + { + case SF_SUBSCRIBE_VIDEO: + strncpy(tempStr, pSubscribe->subscribeFileName + (strlen(pSubscribe->subscribeFileName) - 11), 3); + dirKey = atoi(tempStr); + MLOGD("DIRstr:%s, dirKey:%d\n", tempStr, dirKey); + + strncpy(fileName, pSubscribe->subscribeFileName + (strlen(pSubscribe->subscribeFileName) - 12), 12); + fileKey = atoi(fileName+4); + MLOGD("FileName:%s, fileKey:%d\n", fileName, fileKey); + for(int i=0; ienFileTye = SF_FILE_TYPE_VIDEO; + ret = sf_file_IsExsit((CHAR*)filePath); + if(ret == SF_TRUE) + { + sprintf(pstfileAttr->thumbfileName, "%s", fileName); + sprintf(pstfileAttr->thumbfilePath, "%s", filePath); + MLOGD("fileName:%s\n", pstfileAttr->thumbfileName); + MLOGD("thumbfilePath:%s\n", pstfileAttr->thumbfilePath); + break; + } + } + break; + case SF_SUBSCRIBE_PIC: + strncpy(tempStr, pSubscribe->subscribeFileName + (strlen(pSubscribe->subscribeFileName) - 11), 3); + dirKey = atoi(tempStr); + MLOGD("DIRstr:%s, dirKey:%d\n", tempStr, dirKey); + + strncpy(fileName, pSubscribe->subscribeFileName + (strlen(pSubscribe->subscribeFileName) - 12), 12); + fileKey = atoi(fileName+4); + MLOGD("FileName:%s, fileKey:%d\n", fileName, fileKey); + sprintf(filePath, "%s%s/%03d%s/%s%s", SF_SD_ROOT, SF_DCF_ROOT_DIR_NAME,dirKey, SF_DCF_DIR_NAME_SUFFIX, SF_DCF_FILE_NAME_PREFIX,fileName+4); + MLOGD("srcFile:%s\n", filePath); + + ret = sf_file_IsExsit((CHAR*)filePath); + pstfileAttr->enFileTye = SF_FILE_TYPE_PIC_BIG; + if(ret == SF_TRUE) + { + sprintf(pstfileAttr->thumbfileName, "%s%s", SF_DCF_FILE_NAME_PREFIX,fileName+4); + sprintf(pstfileAttr->thumbfilePath, "%s", filePath); + MLOGD("fileName:%s\n", pstfileAttr->thumbfileName); + MLOGD("thumbfilePath:%s\n", pstfileAttr->thumbfilePath); + } + break; + case SF_SUBSCRIBE_SPEC_FILE: + sprintf(filePath, "%s%s", SF_SD_ROOT,"SF_GPS.TXT" ); + MLOGD("srcFile:%s\n", filePath); + + ret = sf_file_IsExsit((CHAR*)filePath); + pstfileAttr->enFileTye = SF_FILE_TYPE_GPS; + if(ret == SF_TRUE) + { + sprintf(pstfileAttr->thumbfileName, "%s","SF_CAMERA.TXT" ); + sprintf(pstfileAttr->thumbfilePath, "%s", filePath); + MLOGD("fileName:%s\n", pstfileAttr->thumbfileName); + MLOGD("thumbfilePath:%s\n", pstfileAttr->thumbfilePath); + } + break; + default: + MLOGE("CMD[%d] no process!!!\n",pSubscribe->subscribeType); + } + + + if(ret != SF_TRUE) + return SF_FILE_ERROR_NO_FILE; + + return SF_SUCCESS; + +} +#else +SINT32 sf_file_http_header_add(SF_FILE_ATTR_S *pstFileAttr, SF_PDT_PARAM_STATISTICS_S *pStaticParam) +{ + + SF_COMM_CHECK_POINTER(pstFileAttr,SF_FAILURE); + SF_COMM_CHECK_POINTER(pStaticParam,SF_FAILURE); + + SINT32 s32Ret = SF_SUCCESS; + SINT16 i = 0; + SINT16 fd = 0; + SF_CHAR typestr[16] = {0}; + SF_CHAR httpstr[512] = {0}; + SF_CHAR objectName[128] = {0}; + SF_CHAR txtfilename[64] = {0}; + SF_CHAR txtfilePathName[128] = {0}; + SF_CHAR picfilename[36] = {0};//src jpg file + SF_CHAR amzPw[128] = {0}; + SF_CHAR signatureStr[128] = {0}; + SF_CHAR timestr[64] = {0}; + + SLOGD("pstFileAttr->enFileTye:%d\n", pstFileAttr->enFileTye); + SLOGD("pstFileAttr->thumbfileName:%s,%d\n", pstFileAttr->thumbfileName, strlen(pstFileAttr->thumbfileName)); + + printf("pStaticParam http time is %d-%d-%d-%d-%d-%d\r\n", + pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day, \ + pStaticParam->httpTime.Hour, pStaticParam->httpTime.Min, pStaticParam->httpTime.Sec); + sprintf(timestr, "%d%02d%02d%02d%02d%02d", + pStaticParam->httpTime.Year, + pStaticParam->httpTime.Mon, + pStaticParam->httpTime.Day, + pStaticParam->httpTime.Hour, + pStaticParam->httpTime.Min, + pStaticParam->httpTime.Sec); + + if(pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_THUM_3M) + { + sprintf(objectName, "thumb_%s%s", timestr, pstFileAttr->thumbfileName); + sprintf(pstFileAttr->thumbfileName, "%s", objectName); + sprintf(objectName, "%s/%s", pStaticParam->IMEI, pstFileAttr->thumbfileName); + } + else + { + sprintf(objectName, "%s%s", timestr, pstFileAttr->thumbfileName); + sprintf(pstFileAttr->thumbfileName, "%s", objectName); + sprintf(objectName, "%s/%s", pStaticParam->IMEI, pstFileAttr->thumbfileName); + } + + memcpy(picfilename, pstFileAttr->thumbfileName, strlen(pstFileAttr->thumbfileName)-4); + sprintf(txtfilename, "%s.txt", picfilename);/*creat txt file name*/ + + sprintf(txtfilePathName, "%s%s", SF_SD_ROOT, txtfilename); /*creat txt file path*/ + + SLOGD("txtfilePathName =[%s]\n",txtfilePathName); + SLOGD("thumbfilePath =[%s]\n",pstFileAttr->thumbfilePath); + s32Ret = sf_file_size_get(pstFileAttr->thumbfilePath,&pstFileAttr->thumbfileSize); + if(pstFileAttr->thumbfileSize < 0 ||s32Ret == SF_FAILURE) + { + MLOGE("thumbfilePath%s]: filesize error\n", pstFileAttr->thumbfilePath); + return SF_FAILURE; + } + + fd = open(txtfilePathName, O_CREAT|O_RDWR, 0); + if(fd <= 0) + { + MLOGE("create file [%s] failed\n",txtfilePathName); + return SF_FAILURE; + } + + if((pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_THUM_3M) || (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_THUM_5M) || \ + (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_3M) || (pstFileAttr->enFileTye == SF_FILE_TYPE_PIC_5M)) + sprintf(typestr,"image/JPG"); + else if((pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_1080P) || (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_720P) || \ + (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_WVGA) || (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_THUM_1080P) || \ + (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_THUM_720P) || (pstFileAttr->enFileTye == SF_FILE_TYPE_VIDEO_THUM_WVGA)) + sprintf(typestr,"video/MOV"); + else if(pstFileAttr->enFileTye == SF_FILE_TYPE_GPS || pstFileAttr->enFileTye == SF_FILE_TYPE_TRIGGER || pstFileAttr->enFileTye == SF_FILE_TYPE_LOG_ERROR) + sprintf(typestr,"text/plain"); + + for(i=0;i<7;i++) + { + memset(httpstr, '\0', sizeof(httpstr)); + switch(i) + { + case 0: + sprintf(httpstr, "PUT /%s HTTP/1.1\r\n", objectName); + break; + case 1: + sprintf(httpstr, "Host: %s.%s\r\n", pStaticParam->stOssCfg.szBucket, AMZ_HOST);//s3 + break; + case 2: + sprintf(amzPw,"%s%s", AMZ_PW_TITLE, pStaticParam->stOssCfg.szPassword); + amz_signature((UINT8*)signatureStr,pstFileAttr->thumbfileSize,(UINT8*)objectName,(UINT8*)typestr,(UINT8*)amzPw,pStaticParam->stOssCfg.szBucket,pStaticParam->stOssCfg.szIP); + sprintf(httpstr,"Authorization: %s Credential=%s/%d%02d%02d/%s/%s/%s,SignedHeaders=content-length;content-type;host;x-amz-date,Signature=%s\r\n", + SECRET_TYPE, + pStaticParam->stOssCfg.szUsername, + pStaticParam->httpTime.Year, + pStaticParam->httpTime.Mon, + pStaticParam->httpTime.Day, + pStaticParam->stOssCfg.szIP, + AMZ, + SECRET_VER, + signatureStr); + + break; + case 3: + sprintf(httpstr,"Content-Length: %d\r\n",pstFileAttr->thumbfileSize); + break; + case 4: + sprintf(httpstr,"Content-Type: %s\r\n",typestr); + break; + case 5: + sprintf(httpstr,"x-amz-date: %d%02d%02dT%02d%02d%02dZ\r\n", + pStaticParam->httpTime.Year, + pStaticParam->httpTime.Mon, + pStaticParam->httpTime.Day, + pStaticParam->httpTime.Hour, + pStaticParam->httpTime.Min, + pStaticParam->httpTime.Sec); + + break; + case 6: + sprintf(httpstr,"x-amz-content-sha256: UNSIGNED-PAYLOAD\r\n\r\n"); + break; + } + + write(fd, httpstr, strlen(httpstr)); + + } + close(fd); + sync(); + + memset(pstFileAttr->txtfileName, '\0', sizeof(pstFileAttr->txtfileName)); + memset(pstFileAttr->txtfilePath, '\0', sizeof(pstFileAttr->txtfilePath)); + memcpy(pstFileAttr->txtfileName, txtfilename, strlen(txtfilename)); + memcpy(pstFileAttr->txtfilePath, txtfilePathName, strlen(txtfilePathName)); + + return s32Ret; +} + +SINT16 sf_file_subscribe_check(SF_FILE_ATTR_S *pstfileAttr, SF_SEND_FILE_ATTR_S* pSendFileAttr) +{ + UINT16 dirKey = 0; + UINT16 fileKey = 0; +/* + UINT16 videoDirKey = 0; + UINT16 videoFileKey = 0; +*/ + SINT16 ret = 0; + SF_CHAR tempStr[6] = {0}; + SF_CHAR fileName[16] = {0}; + SF_CHAR filePath[128] = {0}; + + memset(pstfileAttr->thumbfileName, '\0', sizeof(pstfileAttr->thumbfileName)); + memset(pstfileAttr->thumbfilePath, '\0', sizeof(pstfileAttr->thumbfilePath)); + memset(pstfileAttr->txtfileName, '\0', sizeof(pstfileAttr->txtfileName)); + memset(pstfileAttr->txtfilePath, '\0', sizeof(pstfileAttr->txtfilePath)); + + + switch(pSendFileAttr->enFileTye) + { + case SF_FILE_TYPE_VIDEO_WVGA: + case SF_FILE_TYPE_VIDEO_720P: + case SF_FILE_TYPE_VIDEO_1080P: + MLOGI("SubFileName [%s]\n",pSendFileAttr->SubFileName); + strncpy(tempStr, pSendFileAttr->SubFileName + (strlen(pSendFileAttr->SubFileName) - 11), 3); + dirKey = atoi(tempStr); + SLOGD("DIRstr:%s, dirKey:%d\n", tempStr, dirKey); + + strncpy(fileName, pSendFileAttr->SubFileName + (strlen(pSendFileAttr->SubFileName) - 12), 12); + fileKey = atoi(fileName+4); + SLOGD("FileName:%s, fileKey:%d\n", fileName, fileKey); + sprintf(filePath, "%s%s/%03d%s/%s%04d.%s", SF_SD_ROOT, SF_DCF_ROOT_DIR_NAME,dirKey, SF_DCF_DIR_NAME_SUFFIX, SF_DCF_FILE_NAME_PREFIX,fileKey,SF_DCF_EXT_MOV); + SLOGD("srcFile:%s\n", filePath); + +// strncpy(fileName, pSendFileAttr->SubFileName + (strlen(pSendFileAttr->SubFileName) - 11), 8); +// sprintf(filePath, "%sS%s%s", SF_4G_SMALL_VIDEO_STREAM_PATH,fileName ,SF_DCF_EXT_MOV); +// SLOGD("srcFile:%s\n", filePath); + + ret = sf_file_IsExsit((CHAR*)filePath); + pstfileAttr->enFileTye = pSendFileAttr->enFileTye; + if(ret != SF_TRUE) { + MLOGW("[%s] not existed in SD!!!\n",filePath); + break; + } + + sprintf(pstfileAttr->thumbfileName, "%s%04d.%s", SF_DCF_FILE_NAME_PREFIX,fileKey,SF_DCF_EXT_MOV); + sprintf(pstfileAttr->thumbfilePath, "%s", filePath); + SLOGD("fileName:%s\n", pstfileAttr->thumbfileName); + SLOGD("thumbfilePath:%s\n", pstfileAttr->thumbfilePath); + + break; + case SF_FILE_TYPE_PIC_3M: + case SF_FILE_TYPE_PIC_5M: + strncpy(tempStr, pSendFileAttr->SubFileName + (strlen(pSendFileAttr->SubFileName) - 11), 3); + dirKey = atoi(tempStr); + SLOGD("DIRstr:%s, dirKey:%d\n", tempStr, dirKey); + + strncpy(fileName, pSendFileAttr->SubFileName + (strlen(pSendFileAttr->SubFileName) - 12), 12); + fileKey = atoi(fileName+4); + SLOGD("FileName:%s, fileKey:%d\n", fileName, fileKey); + sprintf(filePath, "%s%s/%03d%s/%s%s", SF_SD_ROOT, SF_DCF_ROOT_DIR_NAME,dirKey, SF_DCF_DIR_NAME_SUFFIX, SF_DCF_FILE_NAME_PREFIX,fileName+4); + SLOGD("srcFile:%s\n", filePath); + + ret = sf_file_IsExsit((CHAR*)filePath); + pstfileAttr->enFileTye = pSendFileAttr->enFileTye; + + if(ret != SF_TRUE) { + MLOGW("[%s] not existed in SD!!!\n",filePath); + break; + } + + sprintf(pstfileAttr->thumbfileName, "%s%s", SF_DCF_FILE_NAME_PREFIX,fileName+4); + sprintf(pstfileAttr->thumbfilePath, "%s", filePath); + SLOGD("fileName:%s\n", pstfileAttr->thumbfileName); + SLOGD("thumbfilePath:%s\n", pstfileAttr->thumbfilePath); + break; + + case SF_FILE_TYPE_LOG_ERROR: + sprintf(filePath, "%s%s", SF_SD_ROOT,"SF_GPS.TXT" ); + SLOGD("srcFile:%s\n", filePath); + + ret = sf_file_IsExsit((CHAR*)filePath); + pstfileAttr->enFileTye = SF_FILE_TYPE_LOG_ERROR; + + if(ret != SF_TRUE) { + MLOGW("[%s] not existed in SD!!!\n",filePath); + break; + } + + sprintf(pstfileAttr->thumbfileName, "%s","SF_CAMERA.TXT"); + sprintf(pstfileAttr->thumbfilePath, "%s", filePath); + SLOGD("fileName:%s\n", pstfileAttr->thumbfileName); + SLOGD("thumbfilePath:%s\n", pstfileAttr->thumbfilePath); + + break; + + default: + ret = SF_FILE_ERROR_NO_FILE; + SLOGD("CMD[%d] no process!!!\n", pSendFileAttr->enFileTye); + } + + + if(ret != SF_TRUE) + return SF_FILE_ERROR_NO_FILE; + + + return SF_SUCCESS; + +} +#endif + +void sf_file_thumb_cfg_fill(char* filepath,char* fileName,SF_FILE_TYPE_E enFileType) +{ + if(pThumbFileCfg->filecnt >= SF_SRCFILE_MAX) + { + pThumbFileCfg->filecnt = 0; + + } + sprintf(pThumbFileCfg->stfileattr[pThumbFileCfg->filecnt].thumbfilePath, "%s", filepath); + sprintf(pThumbFileCfg->stfileattr[pThumbFileCfg->filecnt].thumbfileName, "%s", fileName); + printf("sf_file_thumb_cfg_fill:enFileType:%d\n",enFileType); + pThumbFileCfg->stfileattr[pThumbFileCfg->filecnt].enFileTye = enFileType; + pThumbFileCfg->filecnt++; + + +} +void sf_file_thumb_cfg_set(SF_SRCFILE_ATTR_S *pThumbFileCfgl) +{ + pThumbFileCfg = pThumbFileCfgl; +} + +SF_SRCFILE_ATTR_S* sf_file_thumb_cfg_get(void) +{ + return pThumbFileCfg; +} +void sf_file_thumb_cfg_clear(void) +{ + pThumbFileCfg->filecnt = 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/gpio/sf_hal_gpio.c b/code/application/source/sf_app/code/source/gpio/sf_hal_gpio.c new file mode 100755 index 000000000..edd179a87 --- /dev/null +++ b/code/application/source/sf_app/code/source/gpio/sf_hal_gpio.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" + +#include "sf_hal_gpio.h" +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +SINT32 sf_hal_gpio_init(U32 gpio_num, int dir) +{ + if (dir == GPIO_DIR_INPUT) + { + gpio_direction_input(gpio_num); + } + else if (dir == GPIO_DIR_OUT) + { + gpio_direction_output(gpio_num, 1); + } + else + { + return SF_FAILURE; + } + /* FILE *fp; + char file_name[64]= {0}; + if(dir == NULL) + { + MLOGE("pointer is NULL\n"); + return SF_FAILURE; + } + + fp = fopen(GPIO_EXPORT, "w"); + if (fp == NULL) + { + MLOGE("Cannot open %s.\n", GPIO_EXPORT); + return SF_FAILURE; + } + + fprintf(fp, "%d", gpio_num); + fclose(fp); + + sprintf(file_name, GPIO_ID_DIR, gpio_num); + fp = fopen(file_name, "rb+"); + if (fp == NULL) + { + MLOGE("Cannot open %s.\n", file_name); + return SF_FAILURE; + } + + fprintf(fp, dir); + + fclose(fp); +*/ +// MLOGI("init gpio pin[%d][%s].\n", gpio_num,dir); + return SF_SUCCESS; +} + +SINT32 sf_hal_gpio_set(U32 gpio_num, U32 nval) +{ + gpio_set_value(gpio_num, nval); + /*FILE *fp; + char file_name[64]= {0}; + U8 buf[10]= {0}; + + sprintf(file_name, GPIO_ID_VALUE, gpio_num); + fp = fopen(file_name, "rb+"); + if (fp == NULL) + { + MLOGE("Cannot open %s.\n", file_name); + return SF_FAILURE; + } + + if(nval == 0) + strcpy((char *)buf,"0"); + else + strcpy((char *)buf,"1"); + + fwrite(buf, sizeof(char), sizeof(buf) - 1, fp); + fclose(fp);*/ + + return SF_SUCCESS; +} + +SINT32 sf_hal_gpio_get(U32 gpio_num, SINT8 *nval) +{ + *nval = (SINT8)gpio_get_value(gpio_num); + /* + FILE *fp; + char file_name[64]= {0}; + U8 buf[10]= {0}; + int snval = 0; + int nret = 0 ; + + sprintf(file_name, GPIO_ID_VALUE, gpio_num); + fp = fopen(file_name, "rb+"); + if (fp == NULL) + { + MLOGE("Cannot open %s.\n", file_name); + return SF_FAILURE; + } + + nret = fread(buf, sizeof(char), sizeof(buf) - 1, fp); + fclose(fp); + + if(nret >0) + { + snval = atoi((char*)&buf[0]); + *nval = (SINT8)snval; + } + else + return SF_FAILURE; +*/ + return SF_SUCCESS; +} +SINT32 sf_hal_gpio_deinit(U32 gpioNum) +{ + /*FILE *fp; + fp = fopen(GPIO_UNEXPORT, "w"); + if (fp == NULL) { + MLOGE("no export gpio[%d]\n", gpioNum); + return SF_FAILURE; + } + fprintf(fp, "%d", gpioNum); + fclose(fp);*/ + return SF_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/logMng/sf_log.c b/code/application/source/sf_app/code/source/logMng/sf_log.c new file mode 100755 index 000000000..b4165a4d6 --- /dev/null +++ b/code/application/source/sf_app/code/source/logMng/sf_log.c @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "sf_base64.h" +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#if SF_ENCRYPTION_ENBLE +U16 gDebugMode = 0; +#else +U16 gDebugMode = 1; +#endif + +int gsave_logtxt = 0; +static SF_LOG_LEVEL_e enLogLevel = SF_LOG_LEVEL_DEBUG; + +/*========================================================================= + * Log * + *=========================================================================*/ +static char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static void log_base64_encode(const char * bindata, char * base64, int binlength, int model) +{ + int i, j; + unsigned char current; + + for (i = 0, j = 0; i < binlength; i += 3) + { + current = (bindata[i] >> 2); + current &= (unsigned char)0x3F; + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30); + if (i + 1 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C); + if (i + 2 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F); + base64[j++] = base64char[(int)current]; + } + if(model) + { + base64[j++] = '\n'; + } + base64[j] = '\0'; + //return base64; +} + +static U16 sf_get_dbgmode(void) +{ + return gDebugMode; +} +SINT32 sf_log_Level_set(SF_LOG_LEVEL_e enLevel) +{ + enLogLevel = enLevel; + return SF_SUCCESS; +} + +SF_LOG_LEVEL_e sf_log_Level_get(void) +{ + return enLogLevel; +} +void sf_log_module(const char *pszFunc, U32 u32Line, const char *pszFmt, ...) +{ + SF_PDT_PARAM_CFG_S* pSfParam = sf_customer_param_get(); + if(pSfParam->DebugMode == 0) + return; + + FILE* flog; + U16 debugMode = sf_get_dbgmode(); + + { + va_list args; + + pszFmt = (NULL == pszFmt) ? "" : pszFmt; + + CHAR timeBuf[128] = { 0 }; + CHAR tmpBuf[512] = { 0 }; + CHAR allBuf[640] = { 0 }; + CHAR enCodeLog[1024] = { 0 }; + +#ifdef SF_LOG_USE_RTC_TIME + SF_PARA_TIME_S dateTime; +#endif + + flog = fopen(LOG_TMP_MOD_FILE_PATH, "at"); + if(flog != NULL) + { + fseek(flog, 0L, SEEK_END); + + +#ifdef SF_LOG_USE_RTC_TIME + sf_sys_rtc_time_get(&dateTime); + sprintf(timeBuf, "[%s-%d]:%04d/%02d/%02d %02d:%02d:%02d ", pszFunc, u32Line, dateTime.Year, dateTime.Mon, dateTime.Day, + dateTime.Hour, dateTime.Min, dateTime.Sec); +#else + time_t timep; + struct tm *p; + time(&timep); + p = gmtime(&timep); + sprintf((char*)timeBuf, "%04d/%02d/%02d %02d:%02d:%02d ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, + p->tm_hour, p->tm_min, p->tm_sec); +#endif + va_start(args, pszFmt); + vsprintf((char*)tmpBuf, pszFmt, args); + + if(debugMode == 0) + { + sprintf((char*)allBuf, "%s%s", timeBuf, tmpBuf); + log_base64_encode((char*)allBuf, (char*)enCodeLog, strlen((char*)allBuf),1); + fprintf(flog, "%s\n", enCodeLog); + } + else + { + + fprintf(flog, "%s%s\n", timeBuf, tmpBuf); + } + + fclose(flog); + } + else + { + MLOGE("LOG file[%s] open fail!\n",LOG_TMP_MOD_FILE_PATH); + } + + fprintf(stdout, "[%s:%d]:",pszFunc, u32Line); + va_start(args, pszFmt); + vfprintf(stdout, pszFmt, args); + va_end(args); + + } + + return; +} +void sf_log_file(SF_LOG_LEVEL_e enLevel,const char *pszFunc, U32 u32Line,char *pszFmt, ...) +{ + SF_LOG_LEVEL_e enDstLevel; + FILE* flog = NULL; + U16 debugMode = sf_get_dbgmode(); + + enDstLevel = sf_log_Level_get(); + if(enLevel <= enDstLevel) + { + va_list args; + + pszFmt = (NULL == pszFmt) ? "" : pszFmt; + + if(enLevel <= SF_LOG_LEVEL_DEBUG) + { + + CHAR tmpBuf[2048] = { 0 }; + CHAR enCodeLog[2048] = { 0 }; + if(sf_customer_param_get()->DebugMode == 1) { + flog = fopen(LOG_AT_FILE_PATH, "at"); + } + else if(enLevel == SF_LOG_LEVEL_ERROR) { + flog = fopen(LOG_AT_FILE_PATH, "at"); + } + else if(enLevel == SF_LOG_LEVEL_INFO) { + flog = fopen(INFO_FILE_PATH, "at"); + } + + if(flog != NULL) + { + fseek(flog, 0L, SEEK_END); + if(enLevel != SF_LOG_LEVEL_WARNING) + { + time_t timep; + struct tm *p; + time(&timep); + p = gmtime(&timep); + + sprintf((char*)tmpBuf,"[%04d/%02d/%02d %02d:%02d:%02d] [%s-%d]:",p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, + p->tm_hour, p->tm_min, p->tm_sec,pszFunc, u32Line); + + + if(debugMode == 1) + { + log_base64_encode((char*)tmpBuf, (char*)enCodeLog, strlen((char*)tmpBuf),1); + fprintf(flog, "%s", enCodeLog); + + va_start(args, pszFmt); + vsprintf((char*)tmpBuf, pszFmt, args); + log_base64_encode((char*)tmpBuf, (char*)enCodeLog, strlen((char*)tmpBuf),1); + fprintf(flog, "%s", enCodeLog); + va_end(args); + } + else + { + fprintf(flog, "%s", tmpBuf); + + va_start(args, pszFmt); + vsprintf((char*)tmpBuf, pszFmt, args); + fprintf(flog, "%s", tmpBuf); + va_end(args); + + } + } + else + { + va_start(args, pszFmt); + vsprintf((char*)tmpBuf, pszFmt, args); + fprintf(flog, "%s", tmpBuf); + va_end(args); + } + fclose(flog); + } + + + } + if(enLevel == SF_LOG_LEVEL_ERROR) + { + fprintf(stdout,LIGHT_RED "[SF ERR][%s:%d]"NONE,pszFunc, u32Line); + } + else if(enLevel == SF_LOG_LEVEL_WARNING) + { + fprintf(stdout,YELLOW "[SF WARN][%s:%d]"NONE,pszFunc, u32Line); + } + else if(enLevel == SF_LOG_LEVEL_INFO) + { + fprintf(stdout,LIGHT_GREEN "[SF INFO][%s:%d]"NONE,pszFunc, u32Line); + } + else if(enLevel == SF_LOG_LEVEL_DEBUG) + { + fprintf(stdout,LIGHT_PURPLE "[SF DBG][%s:%d]"NONE,pszFunc, u32Line); + } + va_start(args, pszFmt); + vfprintf(stdout, pszFmt, args); + va_end(args); + } + + return; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + + diff --git a/code/application/source/sf_app/code/source/paramMng/sf_param_common.c b/code/application/source/sf_app/code/source/paramMng/sf_param_common.c new file mode 100755 index 000000000..1367af8d7 --- /dev/null +++ b/code/application/source/sf_app/code/source/paramMng/sf_param_common.c @@ -0,0 +1,657 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_log.h" +#include "sf_message_queue.h" +#include "sf_param_common.h" +#include "sf_storeMng.h" + +#if 1 +#include +#include +#include +#include +#include "UIInfo/UIInfo.h" + +#define MAKE_FDT_PARTITION_PATH(x) "/nor/partition_"#x + +#define MAKE_FDT_PARTITION_PATH_HELPER(X) MAKE_FDT_PARTITION_PATH(X) +#define PARTITION_PATH_SYS MAKE_FDT_PARTITION_PATH_HELPER(HUNTING_CAMERA_SYS_PARTITION_NAME) +#define XSTR(X) #X +#define STR(X) XSTR(X) + +UIMenuStoreInfo currentInfo = {0}; //#NT#Init the array to zero. +UIMenuStoreInfo origInfo = {0}; /* backup */ + +BOOL bSysReady = 0; +BOOL bAutoSystemReset = FALSE; + +UINT8 isCapRunning = 0; +static SF_STARTUP_TYPE_E StartMode = SF_MCU_STARTUP_ONKEY; + +SF_URL_S sfStOtaUrl = {0}; + +SF_PDT_PARAM_CFG_S StCustomerParam = {0}; +SF_PDT_PARAM_STATISTICS_S Ststatistics= {0}; + +int sf_UIInfo_GetStrgPartitionInfo(unsigned long long *pPartOfs, unsigned long long *pPartSize, const char* fdt_path) +{ + unsigned char *p_fdt = (unsigned char *)fdt_get_base(); + + if (p_fdt == NULL) { + MLOGE("p_fdt is NULL.\n"); + return -1; + } + + int len = 0; + int nodeoffset = 0; + const void *nodep = NULL; /* property node pointer */ + unsigned long long partition_ofs = 0, partition_size = 0; + + nodeoffset = fdt_path_offset(p_fdt, fdt_path); + if (nodeoffset < 0) { + MLOGE("failed to offset for %s = %d \n", fdt_path, nodeoffset); + return -1; + } else { + MLOGI("offset for %s = %d \n", fdt_path, nodeoffset); + } + nodep = fdt_getprop(p_fdt, nodeoffset, "reg", &len); + if (len == 0 || nodep == NULL) { + MLOGE("failed to access reg.\n"); + return -1; + } else { + unsigned long long *p_data = (unsigned long long *)nodep; + partition_ofs = be64_to_cpu(p_data[0]); + partition_size = be64_to_cpu(p_data[1]); + MLOGI("partition reg = <0x%llX 0x%llX> \n", partition_ofs, partition_size); + + *pPartOfs = partition_ofs; + *pPartSize = partition_size; + } + + return 0; +} + +static int find_mtd_device(const char* partition_name, char* result_buf, const UINT32 result_buf_size) +{ + char cmd[128] = {'\0'}; + char rst_file[] = "/tmp/mtd_rst"; + int ret = 0; + + if(!result_buf){ + MLOGE("result buffer can't be null!\n"); + return -1; + } + + /* ************************************************************ + * 1. cat /proc/mtd info (nvt-storage-partition.dtsi) + * 2. escape double quotes with \"(\\\" in IDE) for grep cmd + * 3. substring of matched mtdX + * 4. output /dev/mtdX + * ************************************************************/ + sprintf(cmd, "cat /proc/mtd | grep \\\"%s\\\" | grep -o 'mtd[0-9 ]*' > %s", partition_name, rst_file); + ret = system(cmd); + if(ret){ + MLOGE("find mtd device %s failed!(ret = %d)\n", partition_name, ret); + } + else{ + FILE *rst_fp = NULL; + size_t read_size; + char tmp[128] = {'\0'}; + + rst_fp = fopen(rst_file, "r"); + if(rst_fp){ + read_size = fread(tmp, 1, result_buf_size, rst_fp); + if(read_size <= strlen("mtd") || !strstr(tmp, "mtd")){ + ret = -1; + } + else{ + /* remove newline */ + if(tmp[strlen(tmp) - 1] == 0xA){ + tmp[strlen(tmp) - 1] = '\0'; + } + + snprintf(result_buf, result_buf_size, "/dev/%s", tmp); + } + + MLOGI("RESULT = %s\n", result_buf); + fclose(rst_fp); + } + else{ + ret = -1; + } + } + + if(ret){ + MLOGE("find mtd device %s failed!(ret = %d)\n", partition_name, ret); + } + + return ret; +} + + +static int find_sys_mtd_device(char* result_buf, const UINT32 result_buf_size) +{ + static char* rst = NULL; + int ret = 0; + const char partition_name[] = STR(HUNTING_CAMERA_SYS_PARTITION_NAME); + + /* no need to find twice if partition is already found */ + if(!rst){ + ret = find_mtd_device(partition_name, result_buf, result_buf_size); + if(ret == 0){ + rst = strdup(result_buf); + } + } + else{ + size_t sz = strlen(rst) + 1; + if(result_buf_size < sz){ + MLOGE("result_buf_size can't less than %lu!\n", sz); + ret = -1; + } + else{ + strcpy(result_buf, rst); + ret = 0; + } + } + + if(ret){ + MLOGE("mtd device of partition %s not found!\n", partition_name); + } + + return ret; +} +int sf_customer_param_load(void) +{ + unsigned long long partition_ofs= 0, partition_size = 0; + int ret = -1; + FILE *sys_mtd_fp = NULL; + INT32 rw_len = 0; + UINT32 sectorCnt = 0; + void *tmpInfo = NULL; + size_t read_size; + + sectorCnt = (sizeof(currentInfo) / _EMBMEM_BLK_SIZE_) + (sizeof(currentInfo) % _EMBMEM_BLK_SIZE_)? 1 : 0; + + ret = sf_UIInfo_GetStrgPartitionInfo(&partition_ofs, &partition_size, PARTITION_PATH_SYS); + if ((ret == 0) && (sizeof(currentInfo) < partition_size)) { + + char sys_mtd_dev_path[128] = {'\0'}; + ret = find_sys_mtd_device(sys_mtd_dev_path, sizeof(sys_mtd_dev_path)); + if(ret){ + goto EXIT; + } + + sys_mtd_fp = fopen(sys_mtd_dev_path, "rb"); + if (sys_mtd_fp == NULL) { + printf("open %s failed!\n", sys_mtd_dev_path); + ret = -1; + goto EXIT; + } + + read_size = sectorCnt * _EMBMEM_BLK_SIZE_; + tmpInfo = (void *)malloc(read_size); + if(!tmpInfo){ + printf("allocate tmpInfo failed!\n"); + ret = -1; + goto EXIT; + } + + memset(tmpInfo, 0x0 , read_size); + rw_len = fread(tmpInfo, 1, read_size, sys_mtd_fp); + if (rw_len != (INT32)(read_size)) { + printf("fread size not matched(%d / %ld)\r\n", rw_len, read_size); + ret = -1; + goto EXIT; + } + + if(((UIMenuStoreInfo*)tmpInfo)->uhInfoSize == sizeof(currentInfo)){ + memcpy(¤tInfo, tmpInfo, sizeof(currentInfo)); + } + else{ + printf("menu info size loaded from flash seems incorrect(old:%lu new:%lu), reset menu info\n", + ((UIMenuStoreInfo*)tmpInfo)->uhInfoSize, + sizeof(currentInfo) + ); + //SysResetFlag(); + currentInfo.uhInfoSize = sizeof(currentInfo); + } + + UINT32 sum = MemCheck_CalcCheckSum16Bit((UINT32)tmpInfo, sizeof(currentInfo)); + printf("**************size = %lx / mov size = %u / sum = %lx **************\n", + sizeof(currentInfo), + //((UIMenuStoreInfo*)tmpInfo)->UIParameter[FL_MOVIE_SIZE], + ((UIMenuStoreInfo*)tmpInfo)->UIParameter[CamMode], + sum); + } + +EXIT: + + if(ret){ + //SysResetFlag(); + currentInfo.uhInfoSize = sizeof(currentInfo); + } + //SysCheckFlag(); + origInfo = currentInfo; + + if(sys_mtd_fp){ + fclose(sys_mtd_fp); + sys_mtd_fp = NULL; + } + + if(tmpInfo){ + free(tmpInfo); + tmpInfo = NULL; + } + return ret; +} + +void SysSetFlag(UINT32 uiFlag, UINT32 uiValue) +{ + currentInfo.UIParameter[uiFlag] = uiValue; +} + +UINT32 SysGetFlag(UINT32 uiFlag) +{ + return (currentInfo.UIParameter[uiFlag]); +} + +UIMenuStoreInfo* sf_ui_para_get(void) +{ + return (UIMenuStoreInfo*)¤tInfo; +} + +#endif + + +void sf_sleep_ms(S32 millisecond) +{ + usleep(millisecond * 1000); +} + + +void sf_sleep_s(S32 second) +{ + sleep(second); +} +const SF_CHAR* sf_poweron_type_string(SF_STARTUP_TYPE_E enType) +{ + switch(enType) + { + case SF_MCU_STARTUP_OFF: + return "SF_MCU_STARTUP_OFF"; + case SF_MCU_STARTUP_ONKEY: + return "SF_MCU_STARTUP_ONKEY"; + case SF_MCU_STARTUP_TIMELAPSE: + return "SF_MCU_STARTUP_TIMELAPSE"; + case SF_MCU_STARTUP_NORMAL: + return "SF_MCU_STARTUP_NORMAL"; + case SF_MCU_STARTUP_RING: + return "SF_MCU_STARTUP_RING"; + case SF_MCU_STARTUP_PIR: + return "SF_MCU_STARTUP_PIR"; + case SF_MCU_STARTUP_WARNING: + return "SF_MCU_STARTUP_WARNING"; + case SF_MCU_STARTUP_SERVER: + return "SF_MCU_STARTUP_SERVER"; + case SF_MCU_STARTUP_DP: + return "SF_MCU_STARTUP_DP"; + case SF_MCU_STARTUP_USB: + return "SF_MCU_STARTUP_USB"; + case SF_MCU_STARTUP_RESET: + return "SF_MCU_STARTUP_RESET"; + case SF_MCU_STARTUP_SYN_PARAM: + return "SF_MCU_STARTUP_SYN_PARAM"; + case SF_MCU_STARTUP_BATCH_SEND: + return "SF_MCU_STARTUP_BATCH_SEND"; + default: + return "unknown poweron type!!!"; + } +} + +SF_STARTUP_TYPE_E sf_poweron_type_get(void) +{ + return StartMode; +} + +SINT32 sf_poweron_type_set(SF_STARTUP_TYPE_E enType) +{ + + StartMode = enType; + + MLOGI("poweron type :[%d,%s]\n",StartMode,sf_poweron_type_string(StartMode)); + return SF_SUCCESS; +} + + +SF_URL_S* sf_ota_url_get(void) +{ + return &sfStOtaUrl; +} + + +void sf_customer_param_init(void) +{ + memset(&StCustomerParam, 0, sizeof(SF_PDT_PARAM_CFG_S)); +} + +SF_PDT_PARAM_CFG_S* sf_customer_param_get(void) +{ + return &StCustomerParam; +} +void sf_customer_param_set(SF_PDT_PARAM_CFG_S *pSfCustomerPara) +{ + memcpy(&StCustomerParam,pSfCustomerPara,sizeof(SF_PDT_PARAM_CFG_S)); +} + +void sf_customer_param_reset(SF_PDT_PARAM_CFG_S *psfpdtparam,UINT8 sysRet) +{ + + +} + +SINT32 sf_customer_param_save(SF_PDT_PARAM_CFG_S *pSfCustomerPara) +{ + SF_COMM_CHECK_POINTER(pSfCustomerPara,SF_FAILURE); + SINT32 i = 0; + SINT32 ret = 0; + SINT32 fd = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + + lenth = sizeof(SF_PDT_PARAM_CFG_S); + + fd = open(SIFAR_CUSTOMER_PARAM_PATH, O_CREAT|O_RDWR, 0); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd,SIFAR_CUSTOMER_PARAM_PATH,SF_FAILURE); + for(i=0; i<(lenth - 4); i++) + CheckSum += *((UINT8 *)pSfCustomerPara + i); + pSfCustomerPara->CheckSum = CheckSum; + + ret = write(fd, pSfCustomerPara, lenth); + if(ret != lenth) + MLOGE("save param failed!!!\n"); + fsync(fd); + close(fd); + + return SF_SUCCESS; +} + +void sf_statistics_param_init(void) +{ + memset(&Ststatistics, 0, sizeof(SF_PDT_PARAM_STATISTICS_S)); +} + +SF_PDT_PARAM_STATISTICS_S* sf_statistics_param_get(void) +{ + return &Ststatistics; +} +void sf_statistics_param_reset(SF_PDT_PARAM_STATISTICS_S *pSfPara) +{ + MLOGI("statistics param all reset!!!\n"); + pSfPara->DailyReportNum = 0; + pSfPara->DialyReportFailCnt = 0; + pSfPara->Year = 0; + pSfPara->Mon = 0; + pSfPara->Day = 0; + pSfPara->TriggerTimes = 0; + pSfPara->SubscribeSendCnt = 0; + pSfPara->SubVideoSendCnt = 0; + pSfPara->SendBatchAgain = 0; + pSfPara->DailyReportAgain = 0; + pSfPara->SendDailyCnt = 0; + pSfPara->SendPicDayCnt = 0; + pSfPara->SendDailyThumbCnt = 0; + pSfPara->SendSuccessThumbCnt = 0; + pSfPara->SendDailyOriginalCnt = 0; + pSfPara->SendSuccessOriginalCnt = 0; + pSfPara->SendDailyVideoCnt = 0; + pSfPara->SendSuccessVideoCnt = 0; + pSfPara->SendThumbTotalTime = 0; + pSfPara->SendOriginalTotalTime = 0; + pSfPara->SendVideoTotalTime = 0; + pSfPara->OldFileKey = 0; + pSfPara->SdTotalFile = 0; + pSfPara->SendDailyFailCnt = 0; + pSfPara->SendDailyTimeoutCnt = 0; + pSfPara->SynParamFlag = 0; + pSfPara->SynMcuSet = 0; + pSfPara->InstantFtpRecfg = 0; + pSfPara->GpsPowerONSendFlag = 0; + pSfPara->GpsSendFlag = 0; + pSfPara->GpsSendYear = 0; + pSfPara->GpsSendDay = 0; + pSfPara->GspSendMon = 0; + pSfPara->LowPowerAlarmFlag = 0; + pSfPara->LoginACMFailedCnt = 0; + pSfPara->bindFlag = 0; + +#ifdef SF_VERSION_RELEASE + sprintf(pSfPara->WebIP, "%s", "a-cen.wuyuantech.com"); +#else + sprintf(pSfPara->WebIP, "%s", "acenter.wuyuantech.com"); +#endif + + memset(pSfPara->AcmIP, '\0', sizeof(pSfPara->AcmIP)); + memset(pSfPara->IMEI, '\0', sizeof(pSfPara->IMEI)); + memset(pSfPara->OperatorCode, '\0', sizeof(pSfPara->OperatorCode)); + memset(pSfPara->ApnGPRS, '\0', sizeof(pSfPara->ApnGPRS)); + memset(pSfPara->ApnUsername, '\0', sizeof(pSfPara->ApnUsername)); + memset(pSfPara->ApnPassword, '\0', sizeof(pSfPara->ApnPassword)); + memset(pSfPara->SimID, '\0', sizeof(pSfPara->SimID)); + memset(pSfPara->ModuleVersion, '\0', sizeof(pSfPara->ModuleVersion)); + memset(pSfPara->ModuleSubversion, '\0', sizeof(pSfPara->ModuleSubversion)); + memset(pSfPara->GpsInfo, '\0', sizeof(pSfPara->GpsInfo)); + memset(pSfPara->Latitude, '\0', sizeof(pSfPara->Latitude)); + memset(pSfPara->Longitude, '\0', sizeof(pSfPara->Longitude)); + memset(pSfPara->BindAccount, '\0', sizeof(pSfPara->BindAccount)); + +} +void sf_statistics_param_specify(SF_PDT_PARAM_STATISTICS_S* pStatisticsParam) +{ +#ifdef SF_VERSION_RELEASE + sprintf(pStatisticsParam->WebIP, "%s", "a-cen.wuyuantech.com"); +#else + sprintf(pStatisticsParam->WebIP, "%s", "acenter.wuyuantech.com"); + +#endif +} + +SINT32 sf_statistics_param_save(SF_PDT_PARAM_STATISTICS_S* pStatisticsParam) +{ + SF_COMM_CHECK_POINTER(pStatisticsParam,SF_FAILURE); + + SINT32 i = 0; + SINT32 fd = 0; + SINT32 ret = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + + lenth = sizeof(SF_PDT_PARAM_STATISTICS_S); + + fd = open(SIFAR_STATISTICS_PARAM_PATH, O_CREAT|O_RDWR, 0); + if(fd < 0) { +// MLOGE("errno = [%d,%s]\n",errno,strerror(errno)); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = 0x0113; + stMessageBuf.arg1 = 0; + sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + fd = open(SIFAR_STATISTICS_PARAM_PATH, O_CREAT|O_RDWR, 0); /*open jpg file*/ + if(fd < 0) { + MLOGE("errno = [%d,%s]\n",errno,strerror(errno)); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd,SIFAR_STATISTICS_PARAM_PATH,SF_FAILURE); + } + } + + + for(i=0; i<(lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + pStatisticsParam->CheckSum = CheckSum; + + ret = write(fd, pStatisticsParam, lenth); + if(ret != lenth) + MLOGE("save param failed!!!\n"); + fsync(fd); + close(fd); + + return SF_SUCCESS; +} + + +SINT32 sf_statistics_param_load(SF_PDT_PARAM_STATISTICS_S* pStatisticsParam) +{ + SF_COMM_CHECK_POINTER(pStatisticsParam,SF_FAILURE); + SINT32 i = 0; + SINT32 fd = 0; + UINT32 CheckSum = 0; + UINT32 lenth = 0; + SINT32 ret = SF_SUCCESS; + static SINT32 loadFalg = 0; + SF_PDT_PARAM_CFG_S *pSfCustomerPara = sf_customer_param_get(); + + if(loadFalg) + return SF_SUCCESS; + + loadFalg = 1; + lenth = sizeof(SF_PDT_PARAM_STATISTICS_S); + memset(pStatisticsParam ,0,lenth); + if(pSfCustomerPara->FirstUpdateFlag == SF_TRUE) + { + + sf_statistics_param_reset(pStatisticsParam); + sf_statistics_param_save(pStatisticsParam); + pSfCustomerPara->FirstUpdateFlag = SF_FALSE; + MLOGI("FirstUpdateFlag = [%d],First start!!!,reset all param \n",pSfCustomerPara->FirstUpdateFlag); + return SF_SUCCESS; + } + if(access((char*)SIFAR_STATISTICS_PARAM_PATH, F_OK) == 0) + { + fd = open(SIFAR_STATISTICS_PARAM_PATH, O_RDWR); + if(fd < 0) { + + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = 0x0113; + stMessageBuf.arg1 = 0; + sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + fd = open(SIFAR_STATISTICS_PARAM_PATH, O_RDWR); /*open jpg file*/ + if(fd < 0) { + MLOGE("errno = [%d,%s]\n",errno,strerror(errno)); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd,SIFAR_STATISTICS_PARAM_PATH,SF_FAILURE); + } + } + + read(fd, pStatisticsParam, lenth); + + for(i=0; i<(lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + + if(CheckSum != pStatisticsParam->CheckSum) + { + sf_statistics_param_reset(pStatisticsParam); + for(i=0; i<(lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + pStatisticsParam->CheckSum = CheckSum; + + ret = write(fd, pStatisticsParam, lenth); + if(ret != lenth) + MLOGE("save param failed!!!\n"); + fsync(fd); + } + close(fd); + + } + else + { + fd = open(SIFAR_STATISTICS_PARAM_PATH, O_CREAT|O_RDWR, 0); + if(fd < 0) { + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = 0x0113; + stMessageBuf.arg1 = 0; + sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + fd = open(SIFAR_STATISTICS_PARAM_PATH, O_CREAT|O_RDWR, 0); /*open jpg file*/ + if(fd < 0) { + MLOGE("errno = [%d,%s]\n",errno,strerror(errno)); + SF_APPCOMM_CHECK_OPENFILE_RETURN(fd,SIFAR_STATISTICS_PARAM_PATH,SF_FAILURE); + } + } + + sf_statistics_param_reset(pStatisticsParam); + for(i=0; i<(lenth - 4); i++) + CheckSum += *((UINT8 *)pStatisticsParam + i); + pStatisticsParam->CheckSum = CheckSum; + + ret = write(fd, pStatisticsParam, lenth); + if(ret != lenth) + MLOGE("save param failed!!!\n"); + fsync(fd); + close(fd); + } + + + + MLOGD("SendPicDayCnt::%d\n", pStatisticsParam->SendPicDayCnt); + if(strlen(pStatisticsParam->WebIP) < 1) + sf_statistics_param_specify(pStatisticsParam); + + return SF_SUCCESS; +} +void sf_all_param_reset(void) +{ + sf_customer_param_reset(sf_customer_param_get(),0); + sf_statistics_param_reset(sf_statistics_param_get()); + sf_customer_param_save(sf_customer_param_get()); + sf_statistics_param_save(sf_statistics_param_get()); + MLOGI("param reset successful !!!\n"); +} +void sf_cap_status_set(UINT8 capStatus) +{ + if((capStatus == 0) || (capStatus == 1) || (capStatus == 2)) + isCapRunning = capStatus; + MLOGD("isCapRunning:%d\n", isCapRunning); +} + +UINT8 sf_cap_status_get(void) +{ + return isCapRunning; +} + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/bitstream.c b/code/application/source/sf_app/code/source/qrcodeMng/bitstream.c new file mode 100755 index 000000000..fb0a4f81a --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/bitstream.c @@ -0,0 +1,250 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include + +#include "bitstream.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +BitStream *BitStream_new(void) +{ + BitStream *bstream; + + bstream = (BitStream *)malloc(sizeof(BitStream)); + if(bstream == NULL) return NULL; + + bstream->length = 0; + bstream->data = NULL; + + return bstream; +} + +static int BitStream_allocate(BitStream *bstream, int length) +{ + unsigned char *data; + + if(bstream == NULL) { + return -1; + } + + data = (unsigned char *)malloc(length); + if(data == NULL) { + return -1; + } + + if(bstream->data) { + free(bstream->data); + } + bstream->length = length; + bstream->data = data; + + return 0; +} + +static BitStream *BitStream_newFromNum(int bits, unsigned int num) +{ + unsigned int mask; + int i; + unsigned char *p; + BitStream *bstream; + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + if(BitStream_allocate(bstream, bits)) { + BitStream_free(bstream); + return NULL; + } + + p = bstream->data; + mask = 1 << (bits - 1); + for(i=0; i> 1; + } + + return bstream; +} + +static BitStream *BitStream_newFromBytes(int size, unsigned char *data) +{ + unsigned char mask; + int i, j; + unsigned char *p; + BitStream *bstream; + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + if(BitStream_allocate(bstream, size * 8)) { + BitStream_free(bstream); + return NULL; + } + + p = bstream->data; + for(i=0; i> 1; + } + } + + return bstream; +} + +int BitStream_append(BitStream *bstream, BitStream *arg) +{ + unsigned char *data; + + if(arg == NULL) { + return -1; + } + if(arg->length == 0) { + return 0; + } + if(bstream->length == 0) { + if(BitStream_allocate(bstream, arg->length)) { + return -1; + } + memcpy(bstream->data, arg->data, arg->length); + return 0; + } + + data = (unsigned char *)malloc(bstream->length + arg->length); + if(data == NULL) { + return -1; + } + memcpy(data, bstream->data, bstream->length); + memcpy(data + bstream->length, arg->data, arg->length); + + free(bstream->data); + bstream->length += arg->length; + bstream->data = data; + + return 0; +} + +int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num) +{ + BitStream *b; + int ret; + + if(bits == 0) return 0; + + b = BitStream_newFromNum(bits, num); + if(b == NULL) return -1; + + ret = BitStream_append(bstream, b); + BitStream_free(b); + + return ret; +} + +int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data) +{ + BitStream *b; + int ret; + + if(size == 0) return 0; + + b = BitStream_newFromBytes(size, data); + if(b == NULL) return -1; + + ret = BitStream_append(bstream, b); + BitStream_free(b); + + return ret; +} + +unsigned char *BitStream_toByte(BitStream *bstream) +{ + int i, j, size, bytes; + unsigned char *data, v; + unsigned char *p; + + size = BitStream_size(bstream); + if(size == 0) { + return NULL; + } + data = (unsigned char *)malloc((size + 7) / 8); + if(data == NULL) { + return NULL; + } + + bytes = size / 8; + + p = bstream->data; + for(i=0; idata); + free(bstream); + } +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/mask.c b/code/application/source/sf_app/code/source/qrcodeMng/mask.c new file mode 100755 index 000000000..78656258f --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/mask.c @@ -0,0 +1,366 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mask.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +//__STATIC +int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level) +{ //printf("--------------------Mask_writeFormatInformation start -------------------\n"); + unsigned int format; + unsigned char v; + int i; + int blacks = 0; + + format = QRspec_getFormatInfo(mask, level); + + for(i=0; i<8; i++) { + if(format & 1) { + blacks += 2; + v = 0x85; + } else { + v = 0x84; + } + frame[width * 8 + width - 1 - i] = v; + if(i < 6) { + frame[width * i + 8] = v; + } else { + frame[width * (i + 1) + 8] = v; + } + format= format >> 1; + } + for(i=0; i<7; i++) { + if(format & 1) { + blacks += 2; + v = 0x85; + } else { + v = 0x84; + } + frame[width * (width - 7 + i) + 8] = v; + if(i == 0) { + frame[width * 8 + 7] = v; + } else { + frame[width * 8 + 6 - i] = v; + } + format= format >> 1; + } + // printf("--------------------Mask_writeFormatInformation end -------------------\n"); + return blacks; + +} + +/** + * Demerit coefficients. + * See Section 8.8.2, pp.45, JIS X0510:2004. + */ +#define N1 (3) +#define N2 (3) +#define N3 (40) +#define N4 (10) + +#define MASKMAKER(__exp__) \ + int x, y;\ + int b = 0;\ +\ + for(y=0; y= maskNum) { + errno = EINVAL; + return NULL; + } + + masked = (unsigned char *)malloc(width * width); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + Mask_writeFormatInformation(width, masked, mask, level); + + return masked; +} + + +//static int n1; +//static int n2; +//static int n3; +//static int n4; + +//__STATIC +int Mask_calcN1N3(int length, int *runLength) +{ + int i; + int demerit = 0; + int fact; + + for(i=0; i= 5) { + demerit += N1 + (runLength[i] - 5); + //n1 += N1 + (runLength[i] - 5); + } + if((i & 1)) { + if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) { + fact = runLength[i] / 3; + if(runLength[i-2] == fact && + runLength[i-1] == fact && + runLength[i+1] == fact && + runLength[i+2] == fact) { + if(i == 3 || runLength[i-3] >= 4 * fact) { + demerit += N3; + //n3 += N3; + } else if(i+4 >= length || runLength[i+3] >= 4 * fact) { + demerit += N3; + //n3 += N3; + } + } + } + } + } + + return demerit; +} + +//__STATIC +int Mask_calcN2(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + unsigned char b22, w22; + int demerit = 0; + + p = frame + width + 1; + for(y=1; y + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "mqrspec.h" +#include "mmask.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +//__STATIC +void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned int format; + unsigned char v; + int i; + + format = MQRspec_getFormatInfo(mask, version, level); + + for(i=0; i<8; i++) { + v = 0x84 | (format & 1); + frame[width * (i + 1) + 8] = v; + format = format >> 1; + } + for(i=0; i<7; i++) { + v = 0x84 | (format & 1); + frame[width * 8 + 7 - i] = v; + format = format >> 1; + } +} + +#define MASKMAKER(__exp__) \ + int x, y;\ +\ + for(y=0; y= maskNum) { + errno = EINVAL; + return NULL; + } + + width = MQRspec_getWidth(version); + masked = (unsigned char *)malloc(width * width); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + MMask_writeFormatInformation(version, width, masked, mask, level); + + return masked; +} + +//__STATIC +int MMask_evaluateSymbol(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + int sum1 = 0, sum2 = 0; + + p = frame + width * (width - 1); + for(x=1; x maxScore) { + maxScore = score; + free(bestMask); + bestMask = mask; + mask = (unsigned char *)malloc(width * width); + if(mask == NULL) break; + } + } + free(mask); + return bestMask; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/mqrspec.c b/code/application/source/sf_app/code/source/qrcodeMng/mqrspec.c new file mode 100755 index 000000000..7b7758f1f --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/mqrspec.c @@ -0,0 +1,292 @@ +/* + * qrencode - QR Code encoder + * + * Micor QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "mqrspec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int ec[4]; //< Number of ECC code (bytes) +} MQRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004. + */ +static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = { + { 0, {0, 0, 0, 0}}, + { 11, {2, 0, 0, 0}}, + { 13, {5, 6, 0, 0}}, + { 15, {6, 8, 0, 0}}, + { 17, {8, 10, 14, 0}} +}; + +int MQRspec_getDataLengthBit(int version, QRecLevel level) +{ + int w; + int ecc; + + w = mqrspecCapacity[version].width - 1; + ecc = mqrspecCapacity[version].ec[level]; + if(ecc == 0) return 0; + return w * w - 64 - ecc * 8; +} + +int MQRspec_getDataLength(int version, QRecLevel level)//ȡݵij +{ + return (MQRspec_getDataLengthBit(version, level) + 4) / 8; +} + +int MQRspec_getECCLength(int version, QRecLevel level)//þλij +{ + return mqrspecCapacity[version].ec[level]; +} + +int MQRspec_getWidth(int version)//ȡ +{ + return mqrspecCapacity[version].width; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * See Table 3 (pp.107) of Appendix 1, JIS X0510:2004. + */ +static const int lengthTableBits[4][4] = { + { 3, 4, 5, 6}, + { 0, 3, 4, 5}, + { 0, 0, 4, 5}, + { 0, 0, 3, 4} +}; + +int MQRspec_lengthIndicator(QRencodeMode mode, int version)//ַͰ汾Ϣȷtableʲô +{ + return lengthTableBits[mode][version - 1]; +} + +int MQRspec_maximumWords(QRencodeMode mode, int version) +{ + int bits; + int words; + + bits = lengthTableBits[mode][version - 1]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_mqrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3}, + {0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4}, + {0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d}, + {0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba} +}; + +/* See Table 10 of Appendix 1. (pp.115) */ +static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = { + {-1, -1, -1}, + { 0, -1, -1}, + { 1, 2, -1}, + { 3, 4, -1}, + { 5, 6, 7} +}; + +unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level) +{ + int type; + + if(mask < 0 || mask > 3) return 0; + if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0; + if(level == QR_ECLEVEL_H) return 0; + type = typeTable[version][level]; + if(type < 0) return 0; + + return formatInfo[mask][type]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Cache of initial frames. + */ +/* C99 says that static storage shall be initialized to a null pointer + * by compiler. */ +static unsigned char *frames[MQRSPEC_VERSION_MAX + 1]; +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)//??????????????????????????????????? +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y=0; y<7; y++) { + for(x=0; x<7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + +static unsigned char *MQRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + + memset(frame, 0, width * width); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + /* Separator */ + p = frame; + for(y=0; y<7; y++) { + p[7] = 0xc0; + p += width; + } + memset(frame + width * 7, 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8 + 1, 0x84, 8); + p = frame + width + 8; + for(y=0; y<7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + 8; + q = frame + width * 8; + for(x=1; x MQRSPEC_VERSION_MAX) return NULL; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + if(frames[version] == NULL) { + frames[version] = MQRspec_createFrame(version); + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif + if(frames[version] == NULL) return NULL; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + memcpy(frame, frames[version], width * width); + + return frame; +} + +void MQRspec_clearCache(void) +{ + int i; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + for(i=1; i<=MQRSPEC_VERSION_MAX; i++) { + free(frames[i]); + frames[i] = NULL; + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/qrenc.c b/code/application/source/sf_app/code/source/qrcodeMng/qrenc.c new file mode 100755 index 000000000..d5b89728b --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/qrenc.c @@ -0,0 +1,358 @@ +/** + * qrencode - QR Code encoder + * + * QR Code encoding tool + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include "qrencode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define INCHES_PER_METER (100.0/2.54) + + + +static int casesensitive = 1; +static int eightbit = 0; +static int version= 0; +static int micro = 0; +static QRecLevel level = QR_ECLEVEL_L; +static QRencodeMode hint = QR_MODE_8; + +#define MAX_DATA_SIZE (7090 * 16) /* from the specification */ + +#if 0 +#define SIZE 4 +typedef unsigned char U1; +typedef unsigned short U2; +typedef unsigned long U4; + +typedef unsigned char BOOL; +#define TRUE (0xFFu) +#define FALSE (0x00u) + + + +void vd_SerializeLittleEndianU2(U1 * u1_ap_serial, U2 u2_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u2_a_value; + u1_ap_serial[1] = (U1)(u2_a_value >> 8); + } while(FALSE); +} + +void vd_SerializeLittleEndianU3(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + } while(FALSE); +} + +void vd_SerializeLittleEndianU4(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + u1_ap_serial[3] = (U1)(u4_a_value >> 24); + } while(FALSE); +} + +// AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB +// 76543210765432107654321076543210 +#define BMP_RGBA32(r,g,b,a) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) | ((U4)(U1)(a)<<24) ) +#define BMP_RGB24(r,g,b) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) ) + +// XRRRRRGGGGGBBBBB +// 0432104321043210 +#define BMP_RGBA32TOBMP16(c) (U2)( (((U4)(c)>>9) & 0x7C00u) | (((U4)(c)>>6) & 0x03E0u) | (((U4)(c)>>3) & 0x001F) ) + + +typedef struct { + U4 u4_image_width; + U4 u4_image_height; + U4 u4_widthbyte; + U4 u4_image_size; + U2 u2_bitcount; + U2 u2_palette_size; + U1* u1_p_image_data; +} ST_BITMAP; + +ST_BITMAP * st_g_CreateBitmap(U4 u4_a_width, U4 u4_a_height, U2 u2_a_bitcount) +{ + ST_BITMAP * st_tp_bitmap = NULL; + U4 u4_t_widthbyte = 0; + U4 u4_t_imagesize = 0; + + do + { + if((u4_a_width == 0) || (u4_a_width > 4096)) + break; + + if((u4_a_height == 0) || (u4_a_height > 4096)) + break; + + if((u2_a_bitcount != 16) && (u2_a_bitcount != 24) && (u2_a_bitcount != 32)) + break; + + // 4-byte aligned bytes for a line of image data + u4_t_widthbyte = (u4_a_width * u2_a_bitcount + 31) / 32 * 4; + u4_t_imagesize = (u4_t_widthbyte * u4_a_height); + + st_tp_bitmap = malloc(sizeof(ST_BITMAP) + u4_t_imagesize); // alloc together + if(st_tp_bitmap == NULL) + break; + + memset(st_tp_bitmap, 0, sizeof(ST_BITMAP) + u4_t_imagesize); + + st_tp_bitmap->u4_image_width = u4_a_width; + st_tp_bitmap->u4_image_height = u4_a_height; + st_tp_bitmap->u4_widthbyte = u4_t_widthbyte; + st_tp_bitmap->u4_image_size = u4_t_imagesize; + st_tp_bitmap->u2_bitcount = u2_a_bitcount; + st_tp_bitmap->u2_palette_size = 0; + // pointer to the address next to the struct + st_tp_bitmap->u1_p_image_data = (U1 *)st_tp_bitmap + sizeof(ST_BITMAP); + + } while(FALSE); + + return st_tp_bitmap; +} + +void vd_g_FreeBitmap(ST_BITMAP * st_ap_bitmap) +{ + + do + { + if(st_ap_bitmap == NULL) + break; + + memset(st_ap_bitmap, 0, sizeof(ST_BITMAP)); + free(st_ap_bitmap); + + } while(FALSE); +} + +void vd_g_SaveBitmap(const ST_BITMAP * st_ap_bitmap, const char * sz_ap_path) +{ + + U1 u1_tp_bitmap_header[] = + { + 0x42, 0x4D, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, // 2 AA->FileSize + 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0x28, 0x00, // 10 BB->OffBits + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, // 18 CC->Width + 0xDD, 0xDD, 0x01, 0x00, 0xEE, 0xEE, 0x00, 0x00, // 22 DD->Height + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, // 28 EE->BitCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 34 FF->ImageSize + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + FILE *file_bitmap = NULL; + + U4 u4_t_y; + U4 u4_t_pixel_offset = 0; + + do + { + if(st_ap_bitmap == NULL) + break; + + if((st_ap_bitmap->u2_bitcount != 16) && (st_ap_bitmap->u2_bitcount != 24) && (st_ap_bitmap->u2_bitcount != 32)) + break; + + if(sz_ap_path == NULL) + break; + + file_bitmap = fopen(sz_ap_path, "wb"); + if(file_bitmap == NULL) + break; + + // set bitmap head info + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[2], sizeof(u1_tp_bitmap_header) + st_ap_bitmap->u4_image_size); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[10], sizeof(u1_tp_bitmap_header)); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[18], st_ap_bitmap->u4_image_width); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[22], st_ap_bitmap->u4_image_height); + vd_SerializeLittleEndianU2(&u1_tp_bitmap_header[28], st_ap_bitmap->u2_bitcount); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[34], st_ap_bitmap->u4_image_size); + + // write bitmap file head + fwrite(u1_tp_bitmap_header, sizeof(u1_tp_bitmap_header), 1L, file_bitmap); + + // write bitmap image data, bottom to top + u4_t_pixel_offset = st_ap_bitmap->u4_image_height * st_ap_bitmap->u4_widthbyte; + for(u4_t_y = 0; u4_t_y < st_ap_bitmap->u4_image_height; u4_t_y++) + { + u4_t_pixel_offset -= st_ap_bitmap->u4_widthbyte; + fwrite(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], st_ap_bitmap->u4_widthbyte, 1L, file_bitmap); + } + + + } while(0); + + if(file_bitmap) + fclose(file_bitmap); +} + +void vd_SetBitmapPixel(ST_BITMAP * st_ap_bitmap, U4 u4_a_x, U4 u4_a_y, U4 u4_a_color) +{ + U4 u4_t_pixel_offset = 0; + U2 u2_t_color = 0; + + do + { + + if(st_ap_bitmap == NULL) + break; + + if(u4_a_x >= st_ap_bitmap->u4_image_width) + break; + + if(u4_a_y >= st_ap_bitmap->u4_image_height) + break; + + u4_t_pixel_offset = u4_a_y * st_ap_bitmap->u4_widthbyte + u4_a_x * st_ap_bitmap->u2_bitcount / 8; + + switch(st_ap_bitmap->u2_bitcount) + { + case 16: + u2_t_color = BMP_RGBA32TOBMP16(u4_a_color); + vd_SerializeLittleEndianU2(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u2_t_color); + break; + case 24: + vd_SerializeLittleEndianU3(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + case 32: + vd_SerializeLittleEndianU4(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + default: + break; + } + } while(FALSE); +} + +int writeBMP(QRcode *qrcode, const char *outfile) +{ + ST_BITMAP * st_tp_bitmap = NULL; + int width = 0; + int height = 0; + int w = 0; + int i = 0; + int x = 0; + int y = 0; + unsigned char *p = NULL; + + width = qrcode->width * SIZE; + height = qrcode->width * SIZE; + do + { + // create bitmap, size:20x10 format:RGB555->16 + // also support format RGB888->24 and RGBA8888->32 + st_tp_bitmap = st_g_CreateBitmap(width, height, 16); + if(st_tp_bitmap == NULL) + break; + + // draw pixels on bitmap + p = qrcode->data; + for(y = 0; y < qrcode->width; y++) + { + w = 0; + for(x = 0; x < qrcode->width; x++) + { + for(i = 0; i < SIZE; i++) + { + if (((*p) & (1)) == 1) + { + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y, BMP_RGB24(0, 0, 0)); //white + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+1, BMP_RGB24(0, 0, 0)); //white + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+2, BMP_RGB24(0, 0, 0)); //white + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+3, BMP_RGB24(0, 0, 0)); //white + } + else + { + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y, BMP_RGB24(255, 255, 255)); // black + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+1, BMP_RGB24(255, 255, 255)); // black + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+2, BMP_RGB24(255, 255, 255)); // black + vd_SetBitmapPixel(st_tp_bitmap, w, SIZE*y+3, BMP_RGB24(255, 255, 255)); // black + } + w++; + + } + p++; + + } + + } + + // save to file + vd_g_SaveBitmap(st_tp_bitmap, outfile); + + } while(FALSE); + + if(st_tp_bitmap) + vd_g_FreeBitmap(st_tp_bitmap); + + return 0; +} +#endif +QRcode *encode(const unsigned char *intext, int length) +{ + QRcode *code; + if(micro) { + if(eightbit) { + code = QRcode_encodeDataMQR(length, intext, version, level); + } else { + code = QRcode_encodeStringMQR((char *)intext, version, level, hint, casesensitive); + } + } else { + if(eightbit) { + code = QRcode_encodeData(length, intext, version, level); + } else { + code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive); + } + } + return code; + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/qrencode.c b/code/application/source/sf_app/code/source/qrcodeMng/qrencode.c new file mode 100755 index 000000000..2c415f244 --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/qrencode.c @@ -0,0 +1,684 @@ +/* + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" +#include "rscode.h" +#include "split.h" +#include "mask.h" +#include "mmask.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + unsigned char *data; + int eccLength; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc, RS *rs) +{ + block->dataLength = dl; + block->data = data; + block->eccLength = el; + block->ecc = ecc; + + encode_rs_char(rs, data, ecc); +} + +static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)/*Ѵ;ŵһ*/ +{ + int i; + RSblock *block; + unsigned char *dp, *ep; + RS *rs; + int el, dl; + + dl = QRspec_rsDataCodes1(spec); + el = QRspec_rsEccCodes1(spec); + rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); + if(rs == NULL) return -1; + + block = blocks; + dp = data; + ep = ecc; + for(i=0; idatacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + + QRspec_getEccSpec(input->version, input->level, spec); + + raw->version = input->version; + raw->b1 = QRspec_rsBlockNum1(spec); + raw->dataLength = QRspec_rsDataLength(spec); + raw->eccLength = QRspec_rsEccLength(spec); + raw->ecccode = (unsigned char *)malloc(raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->blocks = QRspec_rsBlockNum(spec); + raw->rsblock = (RSblock *)malloc(sizeof(RSblock)); + memset(raw->rsblock,raw->blocks,sizeof(RSblock)); + if(raw->rsblock == NULL) { + QRraw_free(raw); + return NULL; + } + ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode); + if(ret < 0) { + QRraw_free(raw); + return NULL; + } + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +//__STATIC +unsigned char QRraw_getCode(QRRawCode *raw) +{ + int col, row; + unsigned char ret; + + if(raw->count < raw->dataLength) { + row = raw->count % raw->blocks; + col = raw->count / raw->blocks; + if(col >= raw->rsblock[0].dataLength) { + row += raw->b1; + } + ret = raw->rsblock[row].data[col]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + row = (raw->count - raw->dataLength) % raw->blocks; + col = (raw->count - raw->dataLength) / raw->blocks; + ret = raw->rsblock[row].ecc[col]; + } else { + return 0; + } + raw->count++; + return ret; +} + +//__STATIC +void QRraw_free(QRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + +/****************************************************************************** + * Raw(δӹ) code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +//__STATIC +void MQRraw_free(MQRRawCode *raw); +//__STATIC +MQRRawCode *MQRraw_new(QRinput *input) +{ + MQRRawCode *raw; + RS *rs; + + raw = (MQRRawCode *)malloc(sizeof(MQRRawCode)); + if(raw == NULL) return NULL; + + raw->version = input->version; + raw->dataLength = MQRspec_getDataLength(input->version, input->level); + raw->eccLength = MQRspec_getECCLength(input->version, input->level); + raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level); + raw->datacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + raw->ecccode = (unsigned char *)malloc(raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->rsblock = (RSblock *)malloc(sizeof(RSblock)); + memset(raw->rsblock,1,sizeof(RSblock)); + if(raw->rsblock == NULL) { + MQRraw_free(raw); + return NULL; + } + + rs = init_rs(8, 0x11d, 0, 1, raw->eccLength, 255 - raw->dataLength - raw->eccLength); + if(rs == NULL) { + MQRraw_free(raw); + return NULL; + } + + RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode, rs); + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +//__STATIC +unsigned char MQRraw_getCode(MQRRawCode *raw) +{ + unsigned char ret; + + if(raw->count < raw->dataLength) { + ret = raw->datacode[raw->count]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + ret = raw->ecccode[raw->count - raw->dataLength]; + } else { + return 0; + } + raw->count++; + return ret; +} + +//__STATIC +void MQRraw_free(MQRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + + +/****************************************************************************** + * Frame(ܣ߿) filling() + *****************************************************************************/ + +typedef struct { + int width; + unsigned char *frame; + int x, y; + int dir; + int bit; + int mqr; +} FrameFiller; + +static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr) +{ + FrameFiller *filler; + + filler = (FrameFiller *)malloc(sizeof(FrameFiller)); + if(filler == NULL) return NULL; + filler->width = width; + filler->frame = frame; + filler->x = width - 1; + filler->y = width - 1; + filler->dir = -1; + filler->bit = -1; + filler->mqr = mqr; + + return filler; +} + +static unsigned char *FrameFiller_next(FrameFiller *filler) +{ + unsigned char *p; + int x, y, w; + + if(filler->bit == -1) { + filler->bit = 0; + return filler->frame + filler->y * filler->width + filler->x; + } + + x = filler->x; + y = filler->y; + p = filler->frame; + w = filler->width; + + if(filler->bit == 0) { + x--; + filler->bit++; + } else { + x++; + y += filler->dir; + filler->bit--; + } + + if(filler->dir < 0) { + if(y < 0) { + y = 0; + x -= 2; + filler->dir = 1; + if(!filler->mqr && x == 6) { + x--; + y = 9; + } + } + } else { + if(y == w) { + y = w - 1; + x -= 2; + filler->dir = -1; + if(!filler->mqr && x == 6) { + x--; + y -= 8; + } + } + } + if(x < 0 || y < 0) return NULL; + + filler->x = x; + filler->y = y; + + if(p[y * w + x] & 0x80) { + // This tail recursion could be optimized. + return FrameFiller_next(filler); + } + return &p[y * w + x]; +} + + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ + +//__STATIC +QRcode *QRcode_new(int version, int width, unsigned char *data) +{ + QRcode *qrcode; + + qrcode = (QRcode *)malloc(sizeof(QRcode)); + if(qrcode == NULL) return NULL; + + qrcode->version = version; + qrcode->width = width; + qrcode->data = data; + + return qrcode; +} + +void QRcode_free(QRcode *qrcode) +{ + if(qrcode != NULL) { + free(qrcode->data); + free(qrcode); + } +} + +//__STATIC +QRcode *QRcode_encodeMask(QRinput *input, int mask) +{ + //printf("--------------------QRcode_encodeMask start -------------------\n"); + int width, version; + QRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + FrameFiller *filler; + int i, j; + QRcode *qrcode = NULL; + + if(input->mqr) { + //errno = EINVAL; + return NULL; + } + if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) { + //errno = EINVAL; + return NULL; + } + if(input->level > QR_ECLEVEL_H) { + //errno = EINVAL; + return NULL; + } + + raw = QRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = QRspec_getWidth(version); + frame = QRspec_newFrame(version); + if(frame == NULL) { + QRraw_free(raw); + return NULL; + } + filler = FrameFiller_new(width, frame, 0); + if(filler == NULL) { + QRraw_free(raw); + free(frame); + return NULL; + } + + /* inteleaved data and ecc codes */ + for(i=0; idataLength + raw->eccLength; i++) { + code = QRraw_getCode(raw); + bit = 0x80; + for(j=0; j<8; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + QRraw_free(raw); + raw = NULL; + /* remainder bits */ + j = QRspec_getRemainder(version); + for(i=0; ilevel); + } else { + masked = Mask_makeMask(width, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + qrcode = QRcode_new(version, width, masked); + +EXIT: + QRraw_free(raw); + free(filler); + free(frame); + //printf("--------------------QRcode_encodeMask end -------------------\n"); + return qrcode; + +} + +//__STATIC +QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask) +{ + int width, version; + MQRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + FrameFiller *filler; + int i, j; + QRcode *qrcode = NULL; + + if(!input->mqr) { + //errno = EINVAL; + return NULL; + } + if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) { + //errno = EINVAL; + return NULL; + } + if(input->level > QR_ECLEVEL_Q) { + //errno = EINVAL; + return NULL; + } + + raw = MQRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = MQRspec_getWidth(version); + frame = MQRspec_newFrame(version); + if(frame == NULL) { + MQRraw_free(raw); + return NULL; + } + filler = FrameFiller_new(width, frame, 1); + if(filler == NULL) { + MQRraw_free(raw); + free(frame); + return NULL; + } + + /* inteleaved data and ecc codes */ + for(i=0; idataLength + raw->eccLength; i++) { + code = MQRraw_getCode(raw); + if(raw->oddbits && i == raw->dataLength - 1) { + bit = 1 << raw->oddbits; + for(j=0; joddbits; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } else { + bit = 0x80; + for(j=0; j<8; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + } + MQRraw_free(raw); + raw = NULL; + + /* masking */ + if(mask < 0) { + masked = MMask_mask(version, frame, input->level); + } else { + masked = MMask_makeMask(version, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + + qrcode = QRcode_new(version, width, masked); + +EXIT: + MQRraw_free(raw); + free(filler); + free(frame); + return qrcode; +} + +QRcode *QRcode_encodeInput(QRinput *input) +{ + if(input->mqr) { + return QRcode_encodeMaskMQR(input, -1); + } else { + return QRcode_encodeMask(input, -1); + } +} + +static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive) +{ + //printf("--------------------QRcode_encodeStringReal start -------------------\n"); + QRinput *input; + QRcode *code; + int ret; + + if(string == NULL) { + //errno = EINVAL; + return NULL; + } + if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) { + //errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = Split_splitStringToQRinput(string, input, hint, casesensitive); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + //printf("--------------------QRcode_encodeStringReal end -------------------\n"); + return code; + +} + +QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive); +} + +QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive); +} + +static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr) +{ + QRinput *input; + QRcode *code; + int ret; + + if(data == NULL || length == 0) { + errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = QRinput_append(input, QR_MODE_8, length, data); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + + return code; +} + +QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 0); +} + + +QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 1); +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/qrinput.c b/code/application/source/sf_app/code/source/qrcodeMng/qrinput.c new file mode 100755 index 000000000..7c95f2e0e --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/qrinput.c @@ -0,0 +1,1438 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +/****************************************************************************** + * Utilities + *****************************************************************************/ +int QRinput_isSplittableMode(QRencodeMode mode) +{ + return (mode >= QR_MODE_NUM && mode <= QR_MODE_KANJI); +} + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ + +static QRinput_List *QRinput_List_newEntry(QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + if(QRinput_check(mode, size, data)) { + //errno = EINVAL; + return NULL; + } + + entry = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(entry == NULL) return NULL; + + entry->mode = mode; + entry->size = size; + if(size > 0) { + entry->data = (unsigned char *)malloc(size); + if(entry->data == NULL) { + free(entry); + return NULL; + } + memcpy(entry->data, data, size); + } + entry->bstream = NULL; + entry->next = NULL; + + return entry; +} + +static void QRinput_List_freeEntry(QRinput_List *entry) +{ + if(entry != NULL) { + free(entry->data); + BitStream_free(entry->bstream); + free(entry); + } +} + +static QRinput_List *QRinput_List_dup(QRinput_List *entry) +{ + QRinput_List *n; + + n = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(n == NULL) return NULL; + + n->mode = entry->mode; + n->size = entry->size; + n->data = (unsigned char *)malloc(n->size); + if(n->data == NULL) { + free(n); + return NULL; + } + memcpy(n->data, entry->data, entry->size); + n->bstream = NULL; + n->next = NULL; + + return n; +} + +/****************************************************************************** + * Input Data + *****************************************************************************/ + +QRinput *QRinput_new(void) +{ + return QRinput_new2(0, QR_ECLEVEL_L); +} + +QRinput *QRinput_new2(int version, QRecLevel level) +{ + QRinput *input; + + if(version < 0 || version > QRSPEC_VERSION_MAX || level > QR_ECLEVEL_H) { + //errno = EINVAL; + return NULL; + } + + input = (QRinput *)malloc(sizeof(QRinput)); + if(input == NULL) return NULL; + + input->head = NULL; + input->tail = NULL; + input->version = version; + input->level = level; + input->mqr = 0; + input->fnc1 = 0; + + return input; +} + +QRinput *QRinput_newMQR(int version, QRecLevel level) +{ + QRinput *input; + + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + + input = QRinput_new2(version, level); + if(input == NULL) return NULL; + + input->mqr = 1; + + return input; + +INVALID: + //errno = EINVAL; + return NULL; +} + +int QRinput_getVersion(QRinput *input) +{ + return input->version; +} + +int QRinput_setVersion(QRinput *input, int version) +{ + if(input->mqr || version < 0 || version > QRSPEC_VERSION_MAX) { + //errno = EINVAL; + return -1; + } + + input->version = version; + + return 0; +} + +QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input) +{ + return input->level; +} + +int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level) +{ + if(input->mqr || level > QR_ECLEVEL_H) { + //errno = EINVAL; + return -1; + } + + input->level = level; + + return 0; +} + +int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level) +{ + if(input->mqr) { + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + } else { + if(version < 0 || version > QRSPEC_VERSION_MAX) goto INVALID; + if(level > QR_ECLEVEL_H) goto INVALID; + } + + input->version = version; + input->level = level; + + return 0; + +INVALID: + //errno = EINVAL; + return -1; +} + +static void QRinput_appendEntry(QRinput *input, QRinput_List *entry) +{ + if(input->tail == NULL) { + input->head = entry; + input->tail = entry; + } else { + input->tail->next = entry; + input->tail = entry; + } + entry->next = NULL; +} + +int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + entry = QRinput_List_newEntry(mode, size, data); + if(entry == NULL) { + return -1; + } + + QRinput_appendEntry(input, entry); + + return 0; +} + +/** + * Insert a structured-append header to the head of the input data. + * @param input input data. + * @param size number of structured symbols. + * @param index index number of the symbol. (1 <= index <= size) + * @param parity parity among input data. (NOTE: each symbol of a set of structured symbols has the same parity data) + * @retval 0 success. + * @retval -1 error occurred and errno is set to indeicate the error. See Execptions for the details. + * @throw EINVAL invalid parameter. + * @throw ENOMEM unable to allocate memory. + */ +//__STATIC +int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity) +{ + QRinput_List *entry; + unsigned char buf[3]; + + if(size > MAX_STRUCTURED_SYMBOLS) { + //errno = EINVAL; + return -1; + } + if(index <= 0 || index > MAX_STRUCTURED_SYMBOLS) { + //errno = EINVAL; + return -1; + } + + buf[0] = (unsigned char)size; + buf[1] = (unsigned char)index; + buf[2] = parity; + entry = QRinput_List_newEntry(QR_MODE_STRUCTURE, 3, buf); + if(entry == NULL) { + return -1; + } + + entry->next = input->head; + input->head = entry; + + return 0; +} + +int QRinput_appendECIheader(QRinput *input, unsigned int ecinum) +{ + unsigned char data[4]; + + if(ecinum > 999999) { + //errno = EINVAL; + return -1; + } + + /* We manually create byte array of ecinum because + (unsigned char *)&ecinum may cause bus error on some architectures, */ + data[0] = ecinum & 0xff; + data[1] = (ecinum >> 8) & 0xff; + data[2] = (ecinum >> 16) & 0xff; + data[3] = (ecinum >> 24) & 0xff; + return QRinput_append(input, QR_MODE_ECI, 4, data); +} + +void QRinput_free(QRinput *input) +{ + QRinput_List *list, *next; + + if(input != NULL) { + list = input->head; + while(list != NULL) { + next = list->next; + QRinput_List_freeEntry(list); + list = next; + } + free(input); + } +} + +QRinput *QRinput_dup(QRinput *input) +{ + QRinput *n; + QRinput_List *list, *e; + + if(input->mqr) { + n = QRinput_newMQR(input->version, input->level); + } else { + n = QRinput_new2(input->version, input->level); + } + if(n == NULL) return NULL; + + list = input->head; + while(list != NULL) { + e = QRinput_List_dup(list); + if(e == NULL) { + QRinput_free(n); + return NULL; + } + QRinput_appendEntry(n, e); + list = list->next; + } + + return n; +} + +/****************************************************************************** + * Numeric data + *****************************************************************************/ + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeNum(int size, const char *data) +{ + int i; + + for(i=0; i '9') + return -1; + } + + return 0; +} + +/** + * Estimates the length of the encoded bit stream of numeric data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeNum(int size) +{ + int w; + int bits; + + w = size / 3; + bits = w * 10; + switch(size - w * 3) { + case 1: + bits += 4; + break; + case 2: + bits += 7; + break; + default: + break; + } + + return bits; +} + +/** + * Convert the number data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeModeNum(QRinput_List *entry, int version, int mqr) +{ + int words, i, ret; + unsigned int val; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version > 1) { + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_NUM); + if(ret < 0) goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_NUM, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_NUM); + if(ret < 0) goto ABORT; + + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_NUM, version), entry->size); + if(ret < 0) goto ABORT; + } + + words = entry->size / 3; + for(i=0; idata[i*3 ] - '0') * 100; + val += (entry->data[i*3+1] - '0') * 10; + val += (entry->data[i*3+2] - '0'); + + ret = BitStream_appendNum(entry->bstream, 10, val); + if(ret < 0) goto ABORT; + } + + if(entry->size - words * 3 == 1) { + val = entry->data[words*3] - '0'; + ret = BitStream_appendNum(entry->bstream, 4, val); + if(ret < 0) goto ABORT; + } else if(entry->size - words * 3 == 2) { + val = (entry->data[words*3 ] - '0') * 10; + val += (entry->data[words*3+1] - '0'); + BitStream_appendNum(entry->bstream, 7, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Alphabet-numeric data ĸֵ + *****************************************************************************/ + +const signed char QRinput_anTable[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeAn(int size, const char *data) +{ + int i; + + for(i=0; ibstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 2) { + //errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_AN); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_AN, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_AN); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_AN, version), entry->size); + if(ret < 0) goto ABORT; + } + + words = entry->size / 2; + for(i=0; idata[i*2 ]) * 45; + val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]); + + ret = BitStream_appendNum(entry->bstream, 11, val); + if(ret < 0) goto ABORT; + } + + if(entry->size & 1) { + val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]); + + ret = BitStream_appendNum(entry->bstream, 6, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * 8 bit data + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream of 8 bit data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsMode8(int size) +{ + return size * 8; +} + +/** + * Convert the 8bits data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeMode8(QRinput_List *entry, int version, int mqr) +{ + int ret; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 3) { + //errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_8); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_8, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_8); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_8, version), entry->size); + if(ret < 0) goto ABORT; + } + + ret = BitStream_appendBytes(entry->bstream, entry->size, entry->data); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + + +/****************************************************************************** + * Kanji data + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream of kanji data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeKanji(int size) +{ + return (size / 2) * 13; +} + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeKanji(int size, const unsigned char *data) +{ + int i; + unsigned int val; + + if(size & 1) + return -1; + + for(i=0; i 0x9ffc && val < 0xe040) || val > 0xebbf) { + return -1; + } + } + + return 0; +} + +/** + * Convert the kanji data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid version. + */ +static int QRinput_encodeModeKanji(QRinput_List *entry, int version, int mqr) +{ + int ret, i; + unsigned int val, h; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 2) { + errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_KANJI); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_KANJI, version), entry->size/2); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_KANJI); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_KANJI, version), entry->size/2); + if(ret < 0) goto ABORT; + } + + for(i=0; isize; i+=2) { + val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1]; + if(val <= 0x9ffc) { + val -= 0x8140; + } else { + val -= 0xc140; + } + h = (val >> 8) * 0xc0; + val = (val & 0xff) + h; + + ret = BitStream_appendNum(entry->bstream, 13, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Structured Symbol + *****************************************************************************/ + +/** + * Convert a structure symbol code to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid entry. + */ +static int QRinput_encodeModeStructure(QRinput_List *entry, int mqr) +{ + int ret; + + if(mqr) { + //errno = EINVAL; + return -1; + } + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_STRUCTURE); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 4, entry->data[1] - 1); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 4, entry->data[0] - 1); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 8, entry->data[2]); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * FNC1 + *****************************************************************************/ + +static int QRinput_checkModeFNC1Second(int size, const unsigned char *data) +{ + if(size != 1) return -1; + + return 0; +} + +static int QRinput_encodeModeFNC1Second(QRinput_List *entry, int version) +{ + int ret; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_FNC1SECOND); + if(ret < 0) goto ABORT; + + ret = BitStream_appendBytes(entry->bstream, 1, entry->data); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * ECI header + *****************************************************************************/ +static unsigned int QRinput_decodeECIfromByteArray(unsigned char *data) +{ + int i; + unsigned int ecinum; + + ecinum = 0; + for(i=0; i<4; i++) { + ecinum = ecinum << 8; + ecinum |= data[3-i]; + } + + return ecinum; +} + +int QRinput_estimateBitsModeECI(unsigned char *data) +{ + unsigned int ecinum; + + ecinum = QRinput_decodeECIfromByteArray(data);; + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + return MODE_INDICATOR_SIZE + 8; + } else if(ecinum < 16384) { + return MODE_INDICATOR_SIZE + 16; + } else { + return MODE_INDICATOR_SIZE + 24; + } +} + +static int QRinput_encodeModeECI(QRinput_List *entry, int version) +{ + int ret, words; + unsigned int ecinum, code; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ecinum = QRinput_decodeECIfromByteArray(entry->data);; + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + words = 1; + code = ecinum; + } else if(ecinum < 16384) { + words = 2; + code = 0x8000 + ecinum; + } else { + words = 3; + code = 0xc0000 + ecinum; + } + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_ECI); + if(ret < 0) goto ABORT; + + ret = BitStream_appendNum(entry->bstream, words * 8, code); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Validation֤ + *****************************************************************************/ + +int QRinput_check(QRencodeMode mode, int size, const unsigned char *data) +{ + if((mode == QR_MODE_FNC1FIRST && size < 0) || size <= 0) return -1; + + switch(mode) { + case QR_MODE_NUM: + return QRinput_checkModeNum(size, (const char *)data); + case QR_MODE_AN: + return QRinput_checkModeAn(size, (const char *)data); + case QR_MODE_KANJI: + return QRinput_checkModeKanji(size, data); + case QR_MODE_8: + return 0; + case QR_MODE_STRUCTURE: + return 0; + case QR_MODE_ECI: + return 0; + case QR_MODE_FNC1FIRST: + return 0; + case QR_MODE_FNC1SECOND: + return QRinput_checkModeFNC1Second(size, data); + case QR_MODE_NUL: + break; + } + + return -1; +} + +/****************************************************************************** + * Estimation of the bit length + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream on the current version. + * @param entry + * @param version version of the symbol + * @param mqr + * @return number of bits + */ +static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version, int mqr) +{ + int bits = 0; + int l, m; + int num; + + if(version == 0) version = 1; + + switch(entry->mode) { + case QR_MODE_NUM: + bits = QRinput_estimateBitsModeNum(entry->size); + break; + case QR_MODE_AN: + bits = QRinput_estimateBitsModeAn(entry->size); + break; + case QR_MODE_8: + bits = QRinput_estimateBitsMode8(entry->size); + break; + case QR_MODE_KANJI: + bits = QRinput_estimateBitsModeKanji(entry->size); + break; + case QR_MODE_STRUCTURE: + return STRUCTURE_HEADER_SIZE; + case QR_MODE_ECI: + bits = QRinput_estimateBitsModeECI(entry->data); + break; + case QR_MODE_FNC1FIRST: + return MODE_INDICATOR_SIZE; + break; + case QR_MODE_FNC1SECOND: + return MODE_INDICATOR_SIZE + 8; + default: + return 0; + } + + if(mqr) { + l = QRspec_lengthIndicator(entry->mode, version); + m = version - 1; + bits += l + m; + } else { + l = QRspec_lengthIndicator(entry->mode, version); + m = 1 << l; + num = (entry->size + m - 1) / m; + + bits += num * (MODE_INDICATOR_SIZE + l); + } + + return bits; +} + +/** + * Estimates the length of the encoded bit stream of the data. + * @param input input data + * @param version version of the symbol + * @return number of bits + */ +//__STATIC +int QRinput_estimateBitStreamSize(QRinput *input, int version) +{ + QRinput_List *list; + int bits = 0; + + list = input->head; + while(list != NULL) { + bits += QRinput_estimateBitStreamSizeOfEntry(list, version, input->mqr); + list = list->next; + } + + return bits; +} + +/** + * Estimates the required version number of the symbol. + * @param input input data + * @return required version number + */ +static int QRinput_estimateVersion(QRinput *input) +{ + int bits; + int version, prev; + + version = 0; + do { + prev = version; + bits = QRinput_estimateBitStreamSize(input, prev); + version = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if (version < 0) { + return -1; + } + } while (version > prev); + + return version; +} + +/** + * Returns required length in bytes for specified mode, version and bits. + * @param mode + * @param version + * @param bits + * @return required length of code words in bytes. + */ +//__STATIC +int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits) +{ + int payload, size, chunks, remain, maxsize; + + payload = bits - 4 - QRspec_lengthIndicator(mode, version); + switch(mode) { + case QR_MODE_NUM: + chunks = payload / 10; + remain = payload - chunks * 10; + size = chunks * 3; + if(remain >= 7) { + size += 2; + } else if(remain >= 4) { + size += 1; + } + break; + case QR_MODE_AN: + chunks = payload / 11; + remain = payload - chunks * 11; + size = chunks * 2; + if(remain >= 6) size++; + break; + case QR_MODE_8: + size = payload / 8; + break; + case QR_MODE_KANJI: + size = (payload / 13) * 2; + break; + case QR_MODE_STRUCTURE: + size = payload / 8; + break; + default: + size = 0; + break; + } + maxsize = QRspec_maximumWords(mode, version); + if(size < 0) size = 0; + if(maxsize > 0 && size > maxsize) size = maxsize; + + return size; +} + +/****************************************************************************** + * Data conversion ת + *****************************************************************************/ + +/** + * Convert the input data in the data chunk to a bit stream. + * @param entry + * @return number of bits (>0) or -1 for failure. + */ +static int QRinput_encodeBitStream(QRinput_List *entry, int version, int mqr) +{ + int words, ret; + QRinput_List *st1 = NULL, *st2 = NULL; + + if(entry->bstream != NULL) { + BitStream_free(entry->bstream); + entry->bstream = NULL; + } + + words = QRspec_maximumWords(entry->mode, version); + if(words != 0 && entry->size > words) { + st1 = QRinput_List_newEntry(entry->mode, words, entry->data); + if(st1 == NULL) goto ABORT; + st2 = QRinput_List_newEntry(entry->mode, entry->size - words, &entry->data[words]); + if(st2 == NULL) goto ABORT; + + ret = QRinput_encodeBitStream(st1, version, mqr); + if(ret < 0) goto ABORT; + ret = QRinput_encodeBitStream(st2, version, mqr); + if(ret < 0) goto ABORT; + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) goto ABORT; + ret = BitStream_append(entry->bstream, st1->bstream); + if(ret < 0) goto ABORT; + ret = BitStream_append(entry->bstream, st2->bstream); + if(ret < 0) goto ABORT; + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + } else { + ret = 0; + switch(entry->mode) { + case QR_MODE_NUM: + ret = QRinput_encodeModeNum(entry, version, mqr); + break; + case QR_MODE_AN: + ret = QRinput_encodeModeAn(entry, version, mqr); + break; + case QR_MODE_8: + ret = QRinput_encodeMode8(entry, version, mqr); + break; + case QR_MODE_KANJI: + ret = QRinput_encodeModeKanji(entry, version, mqr); + break; + case QR_MODE_STRUCTURE: + ret = QRinput_encodeModeStructure(entry, mqr); + break; + case QR_MODE_ECI: + ret = QRinput_encodeModeECI(entry, version); + break; + case QR_MODE_FNC1SECOND: + ret = QRinput_encodeModeFNC1Second(entry, version); + default: + break; + } + if(ret < 0) return -1; + } + + return BitStream_size(entry->bstream); +ABORT: + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + return -1; +} + +/** + * Convert the input data to a bit stream. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_createBitStream(QRinput *input) +{ + QRinput_List *list; + int bits, total = 0; + + list = input->head; + while(list != NULL) { + bits = QRinput_encodeBitStream(list, input->version, input->mqr); + if(bits < 0) return -1; + total += bits; + list = list->next; + } + + return total; +} + +/** + * Convert the input data to a bit stream. + * When the version number is given and that is not sufficient, it is increased + * automatically. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw ERANGE input is too large. + */ +static int QRinput_convertData(QRinput *input) +{ + int bits; + int ver; + + ver = QRinput_estimateVersion(input); + if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } + + for(;;) { + bits = QRinput_createBitStream(input); + if(bits < 0) return -1; + ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if(ver < 0) { + //errno = ERANGE; + return -1; + } else if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } else { + break; + } + } + + return 0; +} + +/** + * Append padding bits for the input data. + * @param bstream Bitstream to be appended. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ERANGE input data is too large. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_appendPaddingBit(BitStream *bstream, QRinput *input) +{ + int bits, maxbits, words, maxwords, i, ret; + BitStream *padding = NULL; + unsigned char *padbuf; + int padlen; + + bits = BitStream_size(bstream); + maxwords = QRspec_getDataLength(input->version, input->level); + maxbits = maxwords * 8; + + if(maxbits < bits) { + //errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + if(maxbits - bits <= 4) { + ret = BitStream_appendNum(bstream, maxbits - bits, 0); + goto DONE; + } + + words = (bits + 4 + 7) / 8; + + padding = BitStream_new(); + if(padding == NULL) return -1; + ret = BitStream_appendNum(padding, words * 8 - bits, 0); + if(ret < 0) goto DONE; + + padlen = maxwords - words; + if(padlen > 0) { + padbuf = (unsigned char *)malloc(padlen); + if(padbuf == NULL) { + ret = -1; + goto DONE; + } + for(i=0; iversion, input->level); + maxwords = maxbits / 8; + + if(maxbits < bits) { + //errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + termbits = input->version * 2 + 1; + + if(maxbits - bits <= termbits) { + ret = BitStream_appendNum(bstream, maxbits - bits, 0); + goto DONE; + } + + bits += termbits; + + words = (bits + 7) / 8; + if(maxbits - words * 8 > 0) { + termbits += words * 8 - bits; + if(words == maxwords) termbits += maxbits - words * 8; + } else { + termbits += words * 8 - bits; + } + padding = BitStream_new(); + if(padding == NULL) return -1; + ret = BitStream_appendNum(padding, termbits, 0); + if(ret < 0) goto DONE; + + padlen = maxwords - words; + if(padlen > 0) { + padbuf = (unsigned char *)malloc(padlen); + if(padbuf == NULL) { + ret = -1; + goto DONE; + } + for(i=0; i 0) { + ret = BitStream_appendNum(padding, termbits, 0); + if(ret < 0) goto DONE; + } + } + + ret = BitStream_append(bstream, padding); + +DONE: + BitStream_free(padding); + return ret; +} + +static int QRinput_insertFNC1Header(QRinput *input) +{ + QRinput_List *entry = NULL; + + if(input->fnc1 == 1) { + entry = QRinput_List_newEntry(QR_MODE_FNC1FIRST, 0, NULL); + } else if(input->fnc1 == 2) { + entry = QRinput_List_newEntry(QR_MODE_FNC1SECOND, 1, &(input->appid)); + } + if(entry == NULL) { + return -1; + } + + if(input->head->mode != QR_MODE_STRUCTURE || input->head->mode != QR_MODE_ECI) { + entry->next = input->head; + input->head = entry; + } else { + entry->next = input->head->next; + input->head->next = entry; + } + + return 0; +} + +/** + * Merge all bit streams in the input data. + * @param input input data. + * @return merged bit stream + */ + +//__STATIC +BitStream *QRinput_mergeBitStream(QRinput *input) +{ + BitStream *bstream; + QRinput_List *list; + int ret; + + if(input->mqr) { + if(QRinput_createBitStream(input) < 0) { + return NULL; + } + } else { + if(input->fnc1) { + if(QRinput_insertFNC1Header(input) < 0) { + return NULL; + } + } + if(QRinput_convertData(input) < 0) { + return NULL; + } + } + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + list = input->head; + while(list != NULL) { + ret = BitStream_append(bstream, list->bstream); + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + list = list->next; + } + + return bstream; +} + +/** + * Merge all bit streams in the input data and append padding bits + * @param input input data. + * @return padded merged bit stream + */ + +//__STATIC +BitStream *QRinput_getBitStream(QRinput *input) +{ + BitStream *bstream; + int ret; + + bstream = QRinput_mergeBitStream(input); + if(bstream == NULL) { + return NULL; + } + if(input->mqr) { + ret = QRinput_appendPaddingBitMQR(bstream, input); + } else { + ret = QRinput_appendPaddingBit(bstream, input); + } + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + + return bstream; +} + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ + +unsigned char *QRinput_getByteStream(QRinput *input) +{ + BitStream *bstream; + unsigned char *array; + + bstream = QRinput_getBitStream(input); + if(bstream == NULL) { + return NULL; + } + array = BitStream_toByte(bstream); + BitStream_free(bstream); + + return array; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/qrspec.c b/code/application/source/sf_app/code/source/qrcodeMng/qrspec.c new file mode 100755 index 000000000..85f602487 --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/qrspec.c @@ -0,0 +1,573 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "qrspec.h" +#include "qrinput.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int words; //< Data capacity (bytes) + int remainder; //< Remainder bit (bits) + int ec[4]; //< Number of ECC code (bytes) +} QRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = { + { 0, 0, 0, { 0, 0, 0, 0}}, + { 21, 26, 0, { 7, 10, 13, 17}}, // 1 + { 25, 44, 7, { 10, 16, 22, 28}}, + { 29, 70, 7, { 15, 26, 36, 44}}, + { 33, 100, 7, { 20, 36, 52, 64}}, + { 37, 134, 7, { 26, 48, 72, 88}}, // 5 + { 41, 172, 7, { 36, 64, 96, 112}}, + { 45, 196, 0, { 40, 72, 108, 130}}, + { 49, 242, 0, { 48, 88, 132, 156}}, + { 53, 292, 0, { 60, 110, 160, 192}}, + { 57, 346, 0, { 72, 130, 192, 224}}, //10 + { 61, 404, 0, { 80, 150, 224, 264}}, + { 65, 466, 0, { 96, 176, 260, 308}}, + { 69, 532, 0, { 104, 198, 288, 352}}, + { 73, 581, 3, { 120, 216, 320, 384}}, + { 77, 655, 3, { 132, 240, 360, 432}}, //15 + { 81, 733, 3, { 144, 280, 408, 480}}, + { 85, 815, 3, { 168, 308, 448, 532}}, + { 89, 901, 3, { 180, 338, 504, 588}}, + { 93, 991, 3, { 196, 364, 546, 650}}, + { 97, 1085, 3, { 224, 416, 600, 700}}, //20 + {101, 1156, 4, { 224, 442, 644, 750}}, + {105, 1258, 4, { 252, 476, 690, 816}}, + {109, 1364, 4, { 270, 504, 750, 900}}, + {113, 1474, 4, { 300, 560, 810, 960}}, + {117, 1588, 4, { 312, 588, 870, 1050}}, //25 + {121, 1706, 4, { 336, 644, 952, 1110}}, + {125, 1828, 4, { 360, 700, 1020, 1200}}, + {129, 1921, 3, { 390, 728, 1050, 1260}}, + {133, 2051, 3, { 420, 784, 1140, 1350}}, + {137, 2185, 3, { 450, 812, 1200, 1440}}, //30 + {141, 2323, 3, { 480, 868, 1290, 1530}}, + {145, 2465, 3, { 510, 924, 1350, 1620}}, + {149, 2611, 3, { 540, 980, 1440, 1710}}, + {153, 2761, 3, { 570, 1036, 1530, 1800}}, + {157, 2876, 0, { 570, 1064, 1590, 1890}}, //35 + {161, 3034, 0, { 600, 1120, 1680, 1980}}, + {165, 3196, 0, { 630, 1204, 1770, 2100}}, + {169, 3362, 0, { 660, 1260, 1860, 2220}}, + {173, 3532, 0, { 720, 1316, 1950, 2310}}, + {177, 3706, 0, { 750, 1372, 2040, 2430}} //40 +}; + +int QRspec_getDataLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].words - qrspecCapacity[version].ec[level]; +} + +int QRspec_getECCLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].ec[level]; +} + +int QRspec_getMinimumVersion(int size, QRecLevel level) +{ + int i; + int words; + + for(i=1; i<= QRSPEC_VERSION_MAX; i++) { + words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level]; + if(words >= size) return i; + } + + return -1; +} + +int QRspec_getWidth(int version) +{ + return qrspecCapacity[version].width; +} + +int QRspec_getRemainder(int version) +{ + return qrspecCapacity[version].remainder; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +static const int lengthTableBits[4][3] = { + {10, 12, 14}, + { 9, 11, 13}, + { 8, 16, 16}, + { 8, 10, 12} +}; + +int QRspec_lengthIndicator(QRencodeMode mode, int version) +{ + int l; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + return lengthTableBits[mode][l]; +} + +int QRspec_maximumWords(QRencodeMode mode, int version) +{ + int l; + int bits; + int words; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + bits = lengthTableBits[mode][l]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Table of the error correction code (Reed-Solomon block) + * See Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = { + {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}, + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1 + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, + {{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5 + {{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}}, + {{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}}, + {{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}}, + {{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}}, + {{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10 + {{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}}, + {{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}}, + {{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}}, + {{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}}, + {{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15 + {{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}}, + {{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}}, + {{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}}, + {{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}}, + {{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20 + {{ 4, 4}, {17, 0}, {17, 6}, {19, 6}}, + {{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}}, + {{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}}, + {{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}}, + {{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25 + {{10, 2}, {19, 4}, {28, 6}, {33, 4}}, + {{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}}, + {{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}}, + {{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}}, + {{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30 + {{13, 3}, { 2, 29}, {42, 1}, {23, 28}}, + {{17, 0}, {10, 23}, {10, 35}, {19, 35}}, + {{17, 1}, {14, 21}, {29, 19}, {11, 46}}, + {{13, 6}, {14, 23}, {44, 7}, {59, 1}}, + {{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35 + {{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}}, + {{17, 4}, {29, 14}, {49, 10}, {24, 46}}, + {{ 4, 18}, {13, 32}, {48, 14}, {42, 32}}, + {{20, 4}, {40, 7}, {43, 22}, {10, 67}}, + {{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40 +}; + +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]) +{ + int b1, b2; + int data, ecc; + + b1 = eccTable[version][level][0]; + b2 = eccTable[version][level][1]; + data = QRspec_getDataLength(version, level); + ecc = QRspec_getECCLength(version, level); + + if(b2 == 0) { + spec[0] = b1; + spec[1] = data / b1; + spec[2] = ecc / b1; + spec[3] = spec[4] = 0; + } else { + spec[0] = b1; + spec[1] = data / (b1 + b2); + spec[2] = ecc / (b1 + b2); + spec[3] = b2; + spec[4] = spec[1] + 1; + } +} + +/****************************************************************************** + * Alignment pattern + *****************************************************************************/ + +/** + * Positions of alignment patterns. + * This array includes only the second and the third position of the alignment + * patterns. Rest of them can be calculated from the distance between them. + * + * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + */ +static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = { + { 0, 0}, + { 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5 + {34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10 + {30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15 + {26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20 + {28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25 + {30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30 + {30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35 + {24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40 +}; + +/** + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ +static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + }; + int x, y; + const unsigned char *s; + + frame += (oy - 2) * width + ox - 2; + s = finder; + for(y=0; y<5; y++) { + for(x=0; x<5; x++) { + frame[x] = s[x]; + } + frame += width; + s += 5; + } +} + +static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width) +{ + int d, w, x, y, cx, cy; + + if(version < 2) return; + + d = alignmentPattern[version][1] - alignmentPattern[version][0]; + if(d < 0) { + w = 2; + } else { + w = (width - alignmentPattern[version][0]) / d + 2; + } + + if(w * w - 3 == 1) { + x = alignmentPattern[version][0]; + y = alignmentPattern[version][0]; + QRspec_putAlignmentMarker(frame, width, x, y); + return; + } + + cx = alignmentPattern[version][0]; + for(x=1; x QRSPEC_VERSION_MAX) return 0; + + return versionPattern[version - 7]; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_qrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976}, + {0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0}, + {0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed}, + {0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b} +}; + +unsigned int QRspec_getFormatInfo(int mask, QRecLevel level) +{ + if(mask < 0 || mask > 7) return 0; + + return formatInfo[level][mask]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Cache of initial frames. + */ +/* C99 says that static storage shall be initialized to a null pointer + * by compiler. */ +static unsigned char *frames[QRSPEC_VERSION_MAX + 1]; +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y=0; y<7; y++) { + for(x=0; x<7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + + +static unsigned char *QRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + unsigned int verinfo, v; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + + memset(frame, 0, width * width); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + putFinderPattern(frame, width, width - 7, 0); + putFinderPattern(frame, width, 0, width - 7); + /* Separator */ + p = frame; + q = frame + width * (width - 7); + for(y=0; y<7; y++) { + p[7] = 0xc0; + p[width - 8] = 0xc0; + q[7] = 0xc0; + p += width; + q += width; + } + memset(frame + width * 7, 0xc0, 8); + memset(frame + width * 8 - 8, 0xc0, 8); + memset(frame + width * (width - 8), 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8, 0x84, 9); + memset(frame + width * 9 - 8, 0x84, 8); + p = frame + 8; + for(y=0; y<8; y++) { + *p = 0x84; + p += width; + } + p = frame + width * (width - 7) + 8; + for(y=0; y<7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + width * 6 + 8; + q = frame + width * 8 + 6; + for(x=1; x= 7) { + verinfo = QRspec_getVersionPattern(version); + + p = frame + width * (width - 11); + v = verinfo; + for(x=0; x<6; x++) { + for(y=0; y<3; y++) { + p[width * y + x] = 0x88 | (v & 1); + v = v >> 1; + } + } + + p = frame + width - 11; + v = verinfo; + for(y=0; y<6; y++) { + for(x=0; x<3; x++) { + p[x] = 0x88 | (v & 1); + v = v >> 1; + } + p += width; + } + } + /* and a little bit... */ + frame[width * (width - 8) + 8] = 0x81; + + return frame; +} + +unsigned char *QRspec_newFrame(int version) +{ + unsigned char *frame; + int width; + + if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + if(frames[version] == NULL) { + frames[version] = QRspec_createFrame(version); + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif + if(frames[version] == NULL) return NULL; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + memcpy(frame, frames[version], width * width); + + return frame; +} + +void QRspec_clearCache(void) +{ + int i; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + for(i=1; i<=QRSPEC_VERSION_MAX; i++) { + free(frames[i]); + frames[i] = NULL; + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/rscode.c b/code/application/source/sf_app/code/source/qrcodeMng/rscode.c new file mode 100755 index 000000000..5e677065a --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/rscode.c @@ -0,0 +1,340 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon encoder. This code is taken from Phil Karn's libfec then + * editted and packed into a pair of .c and .h files. + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#ifdef HAVE_LIBPTHREAD +# include +#endif + + +#include "rscode.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs + * + */ +typedef unsigned char data_t; + + +/** + * Reed-Solomon codec control block + */ +struct _RS { + int mm; /* Bits per symbol */ + int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} + + +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define PAD (rs->pad) +#define A0 (NN) + + +/* Initialize a Reed-Solomon codec + * symsize = symbol size, bits + * gfpoly = Field generator polynomial coefficients + * fcr = first root of RS code generator polynomial, index form + * prim = primitive element to generate polynomial roots + * nroots = RS code generator polynomial degree (number of roots) + * pad = padding bytes at front of shortened block + */ +static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + RS *rs; + + +/* Common code for intializing a Reed-Solomon control block (char or int symbols) + * Copyright 2004 Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ +//#undef NULL +//#define NULL ((void *)0) + + int i, j, sr,root,iprim; + + rs = NULL; + /* Check parameter ranges */ + if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){ + goto done; + } + + if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; + rs->nn = (1<pad = pad; + + rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); + if(rs->alpha_to == NULL){ + free(rs); + rs = NULL; + goto done; + } + rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); + if(rs->index_of == NULL){ + free(rs->alpha_to); + free(rs); + rs = NULL; + goto done; + } + + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for(i=0;inn;i++){ + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<nn; + } + if(sr != 1){ + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + rs = NULL; + goto done; + } + + /* Form RS code generator polynomial from its roots */ + rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); + if(rs->genpoly == NULL){ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + rs = NULL; + goto done; + } + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + rs->gfpoly = gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { + rs->genpoly[i+1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--){ + if (rs->genpoly[j] != 0) + rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j-1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + done:; + + return rs; +} + +RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + RS *rs; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&rslist_mutex); +#endif + for(rs = rslist; rs != NULL; rs = rs->next) { + if(rs->pad != pad) continue; + if(rs->nroots != nroots) continue; + if(rs->mm != symsize) continue; + if(rs->gfpoly != gfpoly) continue; + if(rs->fcr != fcr) continue; + if(rs->prim != prim) continue; + + goto DONE; + } + + rs = init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad); + if(rs == NULL) goto DONE; + rs->next = rslist; + rslist = rs; + +DONE: +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&rslist_mutex); +#endif + return rs; +} + + +void free_rs_char(RS *rs) +{ + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); + free(rs); +} + +void free_rs_cache(void) +{ + RS *rs, *next; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&rslist_mutex); +#endif + rs = rslist; + while(rs != NULL) { + next = rs->next; + free_rs_char(rs); + rs = next; + } + rslist = NULL; +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&rslist_mutex); +#endif +} + +/* The guts of the Reed-Solomon encoder, meant to be #included + * into a function body with the following typedefs, macros and variables supplied + * according to the code parameters: + + * data_t - a typedef for the data symbol + * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded + * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols + * NROOTS - the number of roots in the RS code generator polynomial, + * which is the same as the number of parity symbols in a block. + Integer variable or literal. + * + * NN - the total number of symbols in a RS block. Integer variable or literal. + * PAD - the number of pad symbols in a block. Integer variable or literal. + * ALPHA_TO - The address of an array of NN elements to convert Galois field + * elements in index (log) form to polynomial form. Read only. + * INDEX_OF - The address of an array of NN elements to convert Galois field + * elements in polynomial form to index (log) form. Read only. + * MODNN - a function to reduce its argument modulo NN. May be inline or a macro. + * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form + + * The memset() and memmove() functions are used. The appropriate header + * file declaring these functions (usually ) must be included by the calling + * program. + + * Copyright 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ + +#undef A0 +#define A0 (NN) /* Special reserved value encoding zero in index form */ + +void encode_rs_char(RS *rs, const data_t *data, data_t *parity) +{ + int i, j; + data_t feedback; + + memset(parity,0,NROOTS*sizeof(data_t));/*sָijһڴеǰn ֽڵȫΪchָASCIIֵ һֵΪָڴַĴСɵָͨΪڴʼ ䷵ֵΪָsָ롣*/ + + for(i=0;i +#include +#include +#include "sf_bmp.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef unsigned char U1; +typedef unsigned short U2; +typedef unsigned long U4; + +typedef unsigned char BOOL; +#define TRUE (0xFFu) +#define FALSE (0x00u) + + + +void vd_SerializeLittleEndianU2(U1 * u1_ap_serial, U2 u2_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u2_a_value; + u1_ap_serial[1] = (U1)(u2_a_value >> 8); + } while(FALSE); +} + +void vd_SerializeLittleEndianU3(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + } while(FALSE); +} + +void vd_SerializeLittleEndianU4(U1 * u1_ap_serial, U4 u4_a_value) +{ + do + { + if(u1_ap_serial == NULL) + break; + + u1_ap_serial[0] = (U1)u4_a_value; + u1_ap_serial[1] = (U1)(u4_a_value >> 8); + u1_ap_serial[2] = (U1)(u4_a_value >> 16); + u1_ap_serial[3] = (U1)(u4_a_value >> 24); + } while(FALSE); +} + +// AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB +// 76543210765432107654321076543210 +#define BMP_RGBA32(r,g,b,a) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) | ((U4)(U1)(a)<<24) ) +#define BMP_RGB24(r,g,b) (U4)( ((U4)(U1)(r)<<16) | ((U4)(U1)(g)<<8) | (U4)(U1)(b) ) + +// XRRRRRGGGGGBBBBB +// 0432104321043210 +#define BMP_RGBA32TOBMP16(c) (U2)( (((U4)(c)>>9) & 0x7C00u) | (((U4)(c)>>6) & 0x03E0u) | (((U4)(c)>>3) & 0x001F) ) + + +typedef struct { + U4 u4_image_width; + U4 u4_image_height; + U4 u4_widthbyte; + U4 u4_image_size; + U2 u2_bitcount; + U2 u2_palette_size; + U1* u1_p_image_data; +} ST_BITMAP; + +ST_BITMAP * st_g_CreateBitmap(U4 u4_a_width, U4 u4_a_height, U2 u2_a_bitcount) +{ + ST_BITMAP * st_tp_bitmap = NULL; + U4 u4_t_widthbyte = 0; + U4 u4_t_imagesize = 0; + + do + { + if((u4_a_width == 0) || (u4_a_width > 4096)) + break; + + if((u4_a_height == 0) || (u4_a_height > 4096)) + break; + + if((u2_a_bitcount != 16) && (u2_a_bitcount != 24) && (u2_a_bitcount != 32)) + break; + + // 4-byte aligned bytes for a line of image data + u4_t_widthbyte = (u4_a_width * u2_a_bitcount + 31) / 32 * 4; + u4_t_imagesize = (u4_t_widthbyte * u4_a_height); + + st_tp_bitmap = malloc(sizeof(ST_BITMAP) + u4_t_imagesize); // alloc together + if(st_tp_bitmap == NULL) + break; + + memset(st_tp_bitmap, 0, sizeof(ST_BITMAP) + u4_t_imagesize); + + st_tp_bitmap->u4_image_width = u4_a_width; + st_tp_bitmap->u4_image_height = u4_a_height; + st_tp_bitmap->u4_widthbyte = u4_t_widthbyte; + st_tp_bitmap->u4_image_size = u4_t_imagesize; + st_tp_bitmap->u2_bitcount = u2_a_bitcount; + st_tp_bitmap->u2_palette_size = 0; + // pointer to the address next to the struct + st_tp_bitmap->u1_p_image_data = (U1 *)st_tp_bitmap + sizeof(ST_BITMAP); + + } while(FALSE); + + return st_tp_bitmap; +} + +void vd_g_FreeBitmap(ST_BITMAP * st_ap_bitmap) +{ + + do + { + if(st_ap_bitmap == NULL) + break; + + memset(st_ap_bitmap, 0, sizeof(ST_BITMAP)); + free(st_ap_bitmap); + + } while(FALSE); +} + +void vd_g_SaveBitmap(const ST_BITMAP * st_ap_bitmap, const char * sz_ap_path) +{ + + U1 u1_tp_bitmap_header[] = + { + 0x42, 0x4D, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, // 2 AA->FileSize + 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0x28, 0x00, // 10 BB->OffBits + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, // 18 CC->Width + 0xDD, 0xDD, 0x01, 0x00, 0xEE, 0xEE, 0x00, 0x00, // 22 DD->Height + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, // 28 EE->BitCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 34 FF->ImageSize + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + FILE *file_bitmap = NULL; + + U4 u4_t_y; + U4 u4_t_pixel_offset = 0; + + do + { + if(st_ap_bitmap == NULL) + break; + + if((st_ap_bitmap->u2_bitcount != 16) && (st_ap_bitmap->u2_bitcount != 24) && (st_ap_bitmap->u2_bitcount != 32)) + break; + + if(sz_ap_path == NULL) + break; + + file_bitmap = fopen(sz_ap_path, "wb"); + if(file_bitmap == NULL) + break; + + // set bitmap head info + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[2], sizeof(u1_tp_bitmap_header) + st_ap_bitmap->u4_image_size); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[10], sizeof(u1_tp_bitmap_header)); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[18], st_ap_bitmap->u4_image_width); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[22], st_ap_bitmap->u4_image_height); + vd_SerializeLittleEndianU2(&u1_tp_bitmap_header[28], st_ap_bitmap->u2_bitcount); + vd_SerializeLittleEndianU4(&u1_tp_bitmap_header[34], st_ap_bitmap->u4_image_size); + + // write bitmap file head + fwrite(u1_tp_bitmap_header, sizeof(u1_tp_bitmap_header), 1L, file_bitmap); + + // write bitmap image data, bottom to top + u4_t_pixel_offset = st_ap_bitmap->u4_image_height * st_ap_bitmap->u4_widthbyte; + for(u4_t_y = 0; u4_t_y < st_ap_bitmap->u4_image_height; u4_t_y++) + { + u4_t_pixel_offset -= st_ap_bitmap->u4_widthbyte; + fwrite(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], st_ap_bitmap->u4_widthbyte, 1L, file_bitmap); + } + + + } while(0); + + if(file_bitmap) + fclose(file_bitmap); +} + +void vd_SetBitmapPixel(ST_BITMAP * st_ap_bitmap, U4 u4_a_x, U4 u4_a_y, U4 u4_a_color) +{ + U4 u4_t_pixel_offset = 0; + U2 u2_t_color = 0; + + do + { + + if(st_ap_bitmap == NULL) + break; + + if(u4_a_x >= st_ap_bitmap->u4_image_width) + break; + + if(u4_a_y >= st_ap_bitmap->u4_image_height) + break; + + u4_t_pixel_offset = u4_a_y * st_ap_bitmap->u4_widthbyte + u4_a_x * st_ap_bitmap->u2_bitcount / 8; + + switch(st_ap_bitmap->u2_bitcount) + { + case 16: + u2_t_color = BMP_RGBA32TOBMP16(u4_a_color); + vd_SerializeLittleEndianU2(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u2_t_color); + break; + case 24: + vd_SerializeLittleEndianU3(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + case 32: + vd_SerializeLittleEndianU4(&st_ap_bitmap->u1_p_image_data[u4_t_pixel_offset], u4_a_color); + break; + default: + break; + } + } while(FALSE); +} + +int sf_qrcode_bmpfile_write(QRcode *DataInfo, const char *outfile, int magnification) +{ + ST_BITMAP * st_tp_bitmap = NULL; + int width = 0; + int height = 0; + int w = 0; + int i = 0; + int j = 0; + int x = 0; + int y = 0; + unsigned char *p = NULL; + + width = DataInfo->width * magnification; + height = DataInfo->width * magnification; + do + { + // create bitmap, size:20x10 format:RGB555->16 + // also support format RGB888->24 and RGBA8888->32 + st_tp_bitmap = st_g_CreateBitmap(width, height, 16); + if(st_tp_bitmap == NULL) + break; + + // draw pixels on bitmap + p = DataInfo->data; + for(y = 0; y < DataInfo->width; y++) + { + w = 0; + for(x = 0; x < DataInfo->width; x++) + { + for(i = 0; i < magnification; i++) + { + if (((*p) & (1)) == 1) + { + for(j = 0; j < magnification; j++) + { + vd_SetBitmapPixel(st_tp_bitmap, w, magnification*y + j, BMP_RGB24(0, 0, 0)); //white + } + } + else + { + for(j = 0; j < magnification; j++) + { + vd_SetBitmapPixel(st_tp_bitmap, w, magnification*y + j, BMP_RGB24(255, 255, 255)); //white + } + } + w++; + } + p++; + } + } + + // save to file + vd_g_SaveBitmap(st_tp_bitmap, outfile); + } while(FALSE); + + if(st_tp_bitmap) + vd_g_FreeBitmap(st_tp_bitmap); + + return 0; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/sf_qrcode.c b/code/application/source/sf_app/code/source/qrcodeMng/sf_qrcode.c new file mode 100755 index 000000000..88188e706 --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/sf_qrcode.c @@ -0,0 +1,116 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * Ver: 1.0.0 2020.05.22 + * Description: creat +**************************************************************************/ + +#include "qrenc.h" +#include "sf_bmp.h" +#include "sf_log.h" +#include "sf_base64.h" +#include "sf_qrcode.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define SIZE 6 + +static void strConv(char *p) +{ + int i; + int len = strlen(p); + char temp; + + for (i = 0; i < len; ) + { + temp = *(p + i); + if (*(p + i + 1) != '\0') + { + *(p + i) = *(p + i + 1); + *(p + i + 1) = temp; + } + i += 2; + } +} + +static SINT32 sf_qrcode_encrypt(char *psrc_Str,char *pdst_Str) +{ + char encodeStr[160] = { 0 }; + char encodeUrlStr[160] = { 0 }; + + sf_base64_encode(psrc_Str, encodeStr, strlen(psrc_Str), 0); + strConv(encodeStr); + URLEncode(encodeStr, strlen(encodeStr), encodeUrlStr, sizeof(encodeUrlStr)/sizeof(char)); + strcpy(pdst_Str, encodeUrlStr); + return SF_SUCCESS; +} + +static int sf_qrcode_encode(char *intext, int length, char *outfile) +{ + QRcode *qrcode = NULL; + int ret = 0; + + qrcode = encode((const unsigned char *)intext, length); + if(qrcode == NULL) { + printf("Failed to encode the input data"); + return 1; + } + + + ret = sf_qrcode_bmpfile_write(qrcode, outfile, SIZE); + + QRcode_free(qrcode); + + return ret; +} +SINT16 sf_qrcode_create(SF_CHAR *pIMEI,SF_CHAR *pSimID ,SF_CHAR* pVersion) +{ + SINT16 ret = SF_SUCCESS; + SF_CHAR qrsrc_Str[160] = { 0 }; + SF_CHAR qrdst_Str[160] = { 0 }; + if(strlen(pIMEI) == 0 ) { + SLOGE("the current IEMI is null!!!\n"); + return SF_FAILURE; + } + + if(strlen(pVersion) == 0) { + SLOGE("the current Version is null!!!\n"); + return SF_FAILURE; + } + + sprintf(qrsrc_Str, "m2m-%s-%s-%s-%s-T11000001", pIMEI, pSimID,ACCESS_KEY,pVersion); + + MLOGI("qrStr = %s\n",qrsrc_Str); + + sf_qrcode_encrypt(qrsrc_Str,qrdst_Str); + MLOGI("qrStr = %s\n",qrdst_Str); + + sf_qrcode_encode(qrdst_Str, strlen(qrdst_Str), "/mnt/mmc/addCam.bmp"); + MLOGI("addCam.bmp have existed \n"); + return ret; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/qrcodeMng/split.c b/code/application/source/sf_app/code/source/qrcodeMng/split.c new file mode 100755 index 000000000..232580e2d --- /dev/null +++ b/code/application/source/sf_app/code/source/qrcodeMng/split.c @@ -0,0 +1,324 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + + +#include "qrencode.h" +#include "qrinput.h" +#include "qrspec.h" +#include "split.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10) +#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0) + +#if !HAVE_STRDUP +#undef strdup +char *strdup(const char *s) +{ + size_t len = strlen(s) + 1; + void *new = malloc(len); + if(new == NULL) return NULL; + return (char *)memcpy(new, s, len); +} +#endif + +static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint) +{ + unsigned char c, d; + unsigned int word; + + c = string[0]; + + if(c == '\0') return QR_MODE_NUL; + if(isdigit(c)) { + return QR_MODE_NUM; + } else if(isalnum(c)) { + return QR_MODE_AN; + } else if(hint == QR_MODE_KANJI) { + d = string[1]; + if(d != '\0') { + word = ((unsigned int)c << 8) | d; + if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; +} + +static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint); + +static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint) +{ + const char *p; + int ret; + int run; + int dif; + int ln; + QRencodeMode mode; + + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isdigit(*p)) { + p++; + } + run = p - string; + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_8) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + if(mode == QR_MODE_AN) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsModeAn(1) /* + 4 + la */ + - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */; + if(dif > 0) { + return Split_eatAn(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isalnum(*p)) { + if(isdigit(*p)) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsModeAn(p - string) /* + 4 + la */ + + QRinput_estimateBitsModeNum(q - p) + 4 + ln + - QRinput_estimateBitsModeAn(q - string) /* - 4 - la */; + if(dif < 0) { + break; + } else { + p = q; + } + } else { + p++; + } + } + + run = p - string; + + if(*p && !isalnum(*p)) { + dif = QRinput_estimateBitsModeAn(run) + 4 + la + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p; + int ret; + int run; + + p = string; + while(Split_identifyMode(p, hint) == QR_MODE_KANJI) { + p += 2; + } + run = p - string; + ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + QRencodeMode mode; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string + 1; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + break; + } + if(mode == QR_MODE_NUM) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */ + + QRinput_estimateBitsModeNum(q - p) + 4 + ln + - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */; + if(dif < 0) { + break; + } else { + p = q; + } + } else if(mode == QR_MODE_AN) { + q = p; + while(isalnum(*q)) { + q++; + } + dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */ + + QRinput_estimateBitsModeAn(q - p) + 4 + la + - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */; + if(dif < 0) { + break; + } else { + p = q; + } + } else { + p++; + } + } + + run = p - string; + ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_splitString(const char *string, QRinput *input, + QRencodeMode hint) +{ + int length; + QRencodeMode mode; + + if(*string == '\0') return 0; + + mode = Split_identifyMode(string, hint); + if(mode == QR_MODE_NUM) { + length = Split_eatNum(string, input, hint); + } else if(mode == QR_MODE_AN) { + length = Split_eatAn(string, input, hint); + } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) { + length = Split_eatKanji(string, input, hint); + } else { + length = Split_eat8(string, input, hint); + } + if(length == 0) return 0; + if(length < 0) return -1; + return Split_splitString(&string[length], input, hint); +} + +static char *dupAndToUpper(const char *str, QRencodeMode hint) +{ + char *newstr, *p; + QRencodeMode mode; + + newstr = strdup(str); + if(newstr == NULL) return NULL; + + p = newstr; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + p += 2; + } else { + if (*p >= 'a' && *p <= 'z') { + *p = (char)((int)*p - 32); + } + p++; + } + } + + return newstr; +} + +int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive) +{ + char *newstr; + int ret; + + if(string == NULL || *string == '\0') { + return -1; + } + if(!casesensitive) { + newstr = dupAndToUpper(string, hint); + if(newstr == NULL) return -1; + ret = Split_splitString(newstr, input, hint); + free(newstr); + } else { + ret = Split_splitString(string, input, hint); + } + + return ret; +} +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/signatureMng/HMACSHA.c b/code/application/source/sf_app/code/source/signatureMng/HMACSHA.c new file mode 100755 index 000000000..66803c11a --- /dev/null +++ b/code/application/source/sf_app/code/source/signatureMng/HMACSHA.c @@ -0,0 +1,285 @@ +//iamshuke@hotmail.com sha1/sha256/hmac +#include +#include +#include +#include +#include + +#include "sha256.h" +#include "sf_type.h" +#include "sf_param_common.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +#define SHA_BLOCKSIZE 64 +#define AMZ_DEBUG 0 +int hmacLen = 32; + +void convert_to_hexString(UINT8* hexString,UINT8* str, int len) +{ + int i ; + UINT8 hexDigits[16] = { '0', '1', '2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; + //UINT8 tempStr[65] = { 0 }; + + for (i = 0; i < len; i++) + { + int temp_num = 0; + temp_num = str[i]; + if (temp_num < 0) + temp_num = 256 + temp_num; + int d1 = temp_num / 16; + int d2 = temp_num % 16; + printf("%c%c", hexDigits[d1], hexDigits[d2]); + hexString[i * 2] = hexDigits[d1]; + hexString[i * 2 + 1] = hexDigits[d2]; + + } + +} + +/* Function to print the digest */ +void pr_sha(UINT8* s, int t) +{ + int i ; + + for(i=0;i SHA256_HASH_SIZE ? SHA256_HASH_SIZE : *t; + datatranslate(isha, out, *t) ; +} + +void hmac_sha256 +( + const UINT8* k, /* secret key */ + int lk, /* length of the key in bytes */ + const UINT8* d, /* data */ + int ld, /* length of data in bytes */ + UINT8* out, /* output buffer, at least "t" bytes */ + int* t + ) +{ + SHA256Context ictx, octx ; + UINT8 isha[SHA256_HASH_SIZE]; + UINT8 osha[SHA256_HASH_SIZE] ; + UINT8 key[SHA256_HASH_SIZE] ; + UINT8 buf[SHA_BLOCKSIZE] ; + int i ; + + if (lk > SHA_BLOCKSIZE) { + + SHA256Context tctx ; + + SHA256Init(&tctx) ; + SHA256Update(&tctx, k, lk) ; + SHA256Final(&tctx, key) ; + + k = key ; + lk = SHA256_HASH_SIZE ; + } + /**** Inner Digest ****/ + + SHA256Init(&ictx) ; + /* Pad the key for inner digest */ + for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ; + for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ; + SHA256Update(&ictx, buf, SHA_BLOCKSIZE) ; + SHA256Update(&ictx, d, ld) ; + SHA256Final(&ictx, isha) ; + /**** Outter Digest ****/ + + SHA256Init(&octx) ; + /* Pad the key for outter digest */ + + for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ; + for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ; + SHA256Update(&octx, buf, SHA_BLOCKSIZE); + SHA256Update(&octx, isha, SHA256_HASH_SIZE); + SHA256Final(&octx, osha) ; + /* truncate and print the results */ + *t = *t > SHA256_HASH_SIZE ? SHA256_HASH_SIZE : *t; + + datatranslate(osha, out, *t); +} + + +void amz_get_canonicalRequest_sha256(UINT8 *requestSha256,UINT32 content_len, UINT8*objectName,UINT8*typestr,UINT8*bucket) +{ + char canonicalReq[512] = { 0 }; + UINT8 out[65] = {0}; +// UINT32 pos = 0;/* Added by MaxLi 2022/03/02--9:46:21*/ + UINT32 lenCanonicalReq = 0; + int lenOut = 32; + UINT8 hexString[65] = {0}; + char tempbuf[128] = {0}; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = sf_statistics_param_get(); + + sprintf(tempbuf,"PUT\n"); + strcpy(canonicalReq,tempbuf); + + sprintf(tempbuf,"/%s\n\n",objectName); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"content-length:%d\n",content_len); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"content-type:%s\n",typestr); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"host:%s.%s\n",bucket,AMZ_HOST); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"x-amz-date:%d%02d%02dT%02d%02d%02dZ\n\n", pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day, pStaticParam->httpTime.Hour, pStaticParam->httpTime.Min, pStaticParam->httpTime.Sec); + strcat(canonicalReq,tempbuf); + + sprintf(tempbuf,"content-length;content-type;host;x-amz-date\nUNSIGNED-PAYLOAD"); + strcat(canonicalReq,tempbuf); + + printf("CanonicalRequest:\n--------\n%s\n----------\n",canonicalReq); + + lenCanonicalReq = strlen(canonicalReq); + printf("lenCanonicalReq:%d\n----------\n",lenCanonicalReq); + + sha256((UINT8*)canonicalReq, lenCanonicalReq, out, &lenOut); + #if AMZ_DEBUG + pr_sha(out, lenOut); + #endif + convert_to_hexString(hexString, out, lenOut); + + sprintf((char*)requestSha256,"%s",hexString); + + +} +void amz_get_signString(UINT8*signstr,UINT8*region,UINT8*requestSha256) +{ +// UINT32 signPos = 0;/* Added by MaxLi 2022/03/02--9:48:34*/ + char tempbuf[66]={0}; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = sf_statistics_param_get(); + + printf("amz_get_signString begin\n"); + sprintf(tempbuf, "%s\n", SECRET_TYPE); + strcpy((char*)signstr, tempbuf); + + sprintf(tempbuf, "%d%02d%02dT%02d%02d%02dZ\n", pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day, pStaticParam->httpTime.Hour, pStaticParam->httpTime.Min, pStaticParam->httpTime.Sec); + strcat((char*)signstr, tempbuf); + + sprintf(tempbuf, "%d%02d%02d/%s/%s/%s\n", pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day, region, AMZ,SECRET_VER); + strcat((char*)signstr, tempbuf); + + sprintf(tempbuf, "%s", requestSha256); + strcat((char*)signstr, tempbuf); + #if AMZ_DEBUG + printf("signstr:%s\n", signstr); + #endif +} +void amz_signature(UINT8 *signatureStr,UINT32 content_len, UINT8*objectName,UINT8*typestr,UINT8*password,UINT8*bucket,UINT8*region) +{ + UINT8 requestSha256[66] = {0}; + UINT8 signStr[256] = {0}; + UINT8 date[20] = {0}; + UINT8 amz[3] = {0}; + UINT8 secretVer[16] = {0}; + UINT8 hmac_keydate[66] = {0}; + UINT8 hmac_keyregion[66] = {0}; + UINT8 hmac_keyamz[66] = {0}; + UINT8 hmac_keysecretver[66] = {0}; + UINT8 hmac_signature[66] = {0}; + SF_PDT_PARAM_STATISTICS_S *pStaticParam = sf_statistics_param_get(); + + + amz_get_canonicalRequest_sha256(requestSha256,content_len,objectName,typestr,bucket); + printf("requestSha256=%s\n",requestSha256); + + amz_get_signString(signStr,region,requestSha256); + sprintf((char*)date,"%d%02d%02d",pStaticParam->httpTime.Year, pStaticParam->httpTime.Mon, pStaticParam->httpTime.Day); + sprintf((char*)amz,"%s",AMZ); + printf("amz:%s\n",amz); + sprintf((char*)secretVer,"%s",SECRET_VER); + printf("date:%s,key:%s\n",date,password); + hmac_sha256(password, strlen((char*)password), date, strlen((char*)date), hmac_keydate, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYDATE:\n"); + pr_sha(hmac_keydate, hmacLen); + printf("region:%s\n",region); + #endif + + hmac_sha256(hmac_keydate, hmacLen, region, strlen((char*)region), hmac_keyregion, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYREGION:\n"); + pr_sha(hmac_keyregion, hmacLen); + printf("amz:%s\n",amz); + #endif + hmac_sha256(hmac_keyregion, hmacLen, amz, strlen((char*)amz), hmac_keyamz, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYAMZ:\n"); + pr_sha(hmac_keyamz, hmacLen); + printf("secretVer:%s\n",secretVer); + #endif + + hmac_sha256(hmac_keyamz, hmacLen, secretVer, strlen((char*)secretVer), hmac_keysecretver, &hmacLen); + + #if AMZ_DEBUG + printf("HMAC-KEYSECRETVER:\n"); + pr_sha(hmac_keysecretver, hmacLen); + #endif + + hmac_sha256(hmac_keysecretver, hmacLen, signStr, strlen((char*)signStr), hmac_signature, &hmacLen); + + #if 1 + printf("HMAC-SIGNATURER:\n"); + pr_sha(hmac_signature, hmacLen); + #endif + + convert_to_hexString(signatureStr, hmac_signature, hmacLen); + printf("signatureStr:%s\n",signatureStr); + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/signatureMng/aos_util.c b/code/application/source/sf_app/code/source/signatureMng/aos_util.c new file mode 100755 index 000000000..1f588aa9d --- /dev/null +++ b/code/application/source/sf_app/code/source/signatureMng/aos_util.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include + + +#include "aos_util.h" +#include "apr_sha1.h" +#include "sf_type.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + +int aos_base64_encode(const UINT8 *in, int inLen, UINT8 *out) +{ + static const char *ENC = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + UINT8 *original_out = out; + + while (inLen) { + // first 6 bits of UINT8 1 + *out++ = ENC[*in >> 2]; + if (!--inLen) { + // last 2 bits of UINT8 1, 4 bits of 0 + *out++ = ENC[(*in & 0x3) << 4]; + *out++ = '='; + *out++ = '='; + break; + } + // last 2 bits of UINT8 1, first 4 bits of UINT8 2 + *out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)]; + in++; + if (!--inLen) { + // last 4 bits of UINT8 2, 2 bits of 0 + *out++ = ENC[(*in & 0xF) << 2]; + *out++ = '='; + break; + } + // last 4 bits of UINT8 2, first 2 bits of UINT8 3 + *out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)]; + in++; + // last 6 bits of UINT8 3 + *out++ = ENC[*in & 0x3F]; + in++, inLen--; + } + + return (out - original_out); +} + +// HMAC-SHA-1: +// +// K - is key padded with zeros to 512 bits +// m - is message +// OPAD - 0x5c5c5c... +// IPAD - 0x363636... +// +// HMAC(K,m) = SHA1((K ^ OPAD) . SHA1((K ^ IPAD) . m)) + + +void HMAC_SHA1(UINT8 hmac[20], const UINT8 *key, int key_len, + const UINT8 *message, int message_len) +{ + UINT8 kopad[64], kipad[64]; + int i; + UINT8 digest[APR_SHA1_DIGESTSIZE]; + apr_sha1_ctx_t context; + + if (key_len > 64) { + key_len = 64; + } + + for (i = 0; i < key_len; i++) { + kopad[i] = key[i] ^ 0x5c; + kipad[i] = key[i] ^ 0x36; + } + + for ( ; i < 64; i++) { + kopad[i] = 0 ^ 0x5c; + kipad[i] = 0 ^ 0x36; + } + + apr_sha1_init(&context); + apr_sha1_update(&context, (const char *)kipad, 64); + apr_sha1_update(&context, (const char *)message, (unsigned int)message_len); + apr_sha1_final(digest, &context); + + apr_sha1_init(&context); + apr_sha1_update(&context, (const char *)kopad, 64); + apr_sha1_update(&context, (const char *)digest, 20); + apr_sha1_final(hmac, &context); +} + +void oss_sign_headers(UINT8*value,UINT8*datestr,UINT8*namestr,UINT8*typestr,UINT8*password,UINT8*bucket) +{ +// int b64Len; + UINT8 hmac[20]; + UINT8 b64[((20 + 1) * 4) / 3]; + UINT8 access_key_secret[64]; + UINT8 signstr[150];/*WARNING!!!, need to adjust the array len,avoid the array bounds*/ + UINT8 b64str[29]={0}; + + sprintf((char*)access_key_secret,"%s",password);//"N2mzlsRZUpGITLBZ03vxMMhUfZSvEl" + sprintf((char*)signstr,"PUT\n\n%s\n%s\n/%s/%s",typestr,datestr,bucket,namestr); + printf("signstr:%s--\n",signstr); + + //printf("+++%d,%d+++\n",strlen(access_key_secret),strlen(signstr)); + HMAC_SHA1(hmac, access_key_secret,strlen((char*)access_key_secret),signstr,strlen((char*)signstr)); + + // Now base-64 encode the results +// b64Len = aos_base64_encode(hmac, 20, b64); + aos_base64_encode(hmac, 20, b64); + #if 0 + int i; + for(i = 0;i<28;i++) + { + printf("%c",b64[i]); + } + printf("\nb64---------------------\n"); + #endif + printf("b64:%s--\n",b64); + strncpy((char*)b64str,(char*)b64,28); + #if 0 + for(i = 0;i<28;i++) + { + printf("%c",b64str[i]); + } + printf("\nb64str---------------------\n"); + #endif + printf("b64str:%s--\n",b64str); + sprintf((char*)value, "%s",b64str); + return; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/signatureMng/apr_sha1.c b/code/application/source/sf_app/code/source/signatureMng/apr_sha1.c new file mode 100755 index 000000000..a57f1484d --- /dev/null +++ b/code/application/source/sf_app/code/source/signatureMng/apr_sha1.c @@ -0,0 +1,376 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The exported function: + * + * apr_sha1_base64(const char *clear, int len, char *out); + * + * provides a means to SHA1 crypt/encode a plaintext password in + * a way which makes password files compatible with those commonly + * used in netscape web and ldap installations. It was put together + * by Clinton Wong , who also notes that: + * + * Note: SHA1 support is useful for migration purposes, but is less + * secure than Apache's password format, since Apache's (MD5) + * password format uses a random eight character salt to generate + * one of many possible hashes for the same password. Netscape + * uses plain SHA1 without a salt, so the same password + * will always generate the same hash, making it easier + * to break since the search space is smaller. + * + * See also the documentation in support/SHA1 as to hints on how to + * migrate an existing netscape installation and other supplied utitlites. + * + * This software also makes use of the following component: + * + * NIST Secure Hash Algorithm + * heavily modified by Uwe Hollerbach uh@alumni.caltech edu + * from Peter C. Gutmann's implementation as found in + * Applied Cryptography by Bruce Schneier + * This code is hereby placed in the public domain + */ + +#include "apr_sha1.h" +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + +/* a bit faster & bigger, if defined */ +#define UNROLL_LOOPS + +/* NIST's proposed modification to SHA, 7/11/94 */ +#define USE_MODIFIED_SHA + +/* SHA f()-functions */ +#define f1(x,y,z) ((x & y) | (~x & z)) +#define f2(x,y,z) (x ^ y ^ z) +#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) +#define f4(x,y,z) (x ^ y ^ z) + +/* SHA constants */ +#define CONST1 0x5a827999L +#define CONST2 0x6ed9eba1L +#define CONST3 0x8f1bbcdcL +#define CONST4 0xca62c1d6L + +/* 32-bit rotate */ + +#define ROT32(x,n) ((x << n) | (x >> (32 - n))) + +#define FUNC(n,i) \ + temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \ + E = D; D = C; C = ROT32(B,30); B = A; A = temp + +#define SHA_BLOCKSIZE 64 + +#if APR_CHARSET_EBCDIC +static apr_xlate_t *ebcdic2ascii_xlate; + +APU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x) +{ + apr_status_t rv; + int onoff; + + /* Only single-byte conversion is supported. + */ + rv = apr_xlate_sb_get(x, &onoff); + if (rv) { + return rv; + } + if (!onoff) { /* If conversion is not single-byte-only */ + return APR_EINVAL; + } + ebcdic2ascii_xlate = x; + return APR_SUCCESS; +} +#endif + +/* do SHA transformation */ +static void sha_transform(apr_sha1_ctx_t *sha_info) +{ + int i; + UINT32 temp, A, B, C, D, E, W[80]; + + for (i = 0; i < 16; ++i) { + W[i] = sha_info->data[i]; + } + for (i = 16; i < 80; ++i) { + W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; +#ifdef USE_MODIFIED_SHA + W[i] = ROT32(W[i], 1); +#endif /* USE_MODIFIED_SHA */ + } + A = sha_info->digest[0]; + B = sha_info->digest[1]; + C = sha_info->digest[2]; + D = sha_info->digest[3]; + E = sha_info->digest[4]; +#ifdef UNROLL_LOOPS + FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4); + FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9); + FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14); + FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19); + + FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24); + FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29); + FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34); + FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39); + + FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44); + FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49); + FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54); + FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59); + + FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64); + FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69); + FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74); + FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79); +#else /* !UNROLL_LOOPS */ + for (i = 0; i < 20; ++i) { + FUNC(1,i); + } + for (i = 20; i < 40; ++i) { + FUNC(2,i); + } + for (i = 40; i < 60; ++i) { + FUNC(3,i); + } + for (i = 60; i < 80; ++i) { + FUNC(4,i); + } +#endif /* !UNROLL_LOOPS */ + sha_info->digest[0] += A; + sha_info->digest[1] += B; + sha_info->digest[2] += C; + sha_info->digest[3] += D; + sha_info->digest[4] += E; +} + +union endianTest { + long Long; + char Char[sizeof(long)]; +}; + +static char isLittleEndian(void) +{ + static union endianTest u; + u.Long = 1; + return (u.Char[0] == 1); +} + +/* change endianness of data */ + +/* count is the number of bytes to do an endian flip */ +static void maybe_byte_reverse(UINT32 *buffer, int count) +{ + int i; + UINT8 ct[4], *cp; + + if (isLittleEndian()) { /* do the swap only if it is little endian */ + count /= sizeof(UINT32); + cp = (UINT8 *) buffer; + for (i = 0; i < count; ++i) { + ct[0] = cp[0]; + ct[1] = cp[1]; + ct[2] = cp[2]; + ct[3] = cp[3]; + cp[0] = ct[3]; + cp[1] = ct[2]; + cp[2] = ct[1]; + cp[3] = ct[0]; + cp += sizeof(UINT32); + } + } +} + +/* initialize the SHA digest */ + +APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info) +{ + sha_info->digest[0] = 0x67452301L; + sha_info->digest[1] = 0xefcdab89L; + sha_info->digest[2] = 0x98badcfeL; + sha_info->digest[3] = 0x10325476L; + sha_info->digest[4] = 0xc3d2e1f0L; + sha_info->count_lo = 0L; + sha_info->count_hi = 0L; + sha_info->local = 0; +} + +/* update the SHA digest */ + +APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info, + const unsigned char *buffer, + unsigned int count) +{ + unsigned int i; + + if ((sha_info->count_lo + ((UINT32) count << 3)) < sha_info->count_lo) { + ++sha_info->count_hi; + } + sha_info->count_lo += (UINT32) count << 3; + sha_info->count_hi += (UINT32) count >> 29; + if (sha_info->local) { + i = SHA_BLOCKSIZE - sha_info->local; + if (i > count) { + i = count; + } + memcpy(((UINT8 *) sha_info->data) + sha_info->local, buffer, i); + count -= i; + buffer += i; + sha_info->local += i; + if (sha_info->local == SHA_BLOCKSIZE) { + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + else { + return; + } + } + while (count >= SHA_BLOCKSIZE) { + memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); + buffer += SHA_BLOCKSIZE; + count -= SHA_BLOCKSIZE; + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + memcpy(sha_info->data, buffer, count); + sha_info->local = count; +} + +APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf, + unsigned int count) +{ +#if APR_CHARSET_EBCDIC + int i; + const UINT8 *buffer = (const UINT8 *) buf; + apr_size_t inbytes_left, outbytes_left; + + if ((sha_info->count_lo + ((UINT32) count << 3)) < sha_info->count_lo) { + ++sha_info->count_hi; + } + sha_info->count_lo += (UINT32) count << 3; + sha_info->count_hi += (UINT32) count >> 29; + /* Is there a remainder of the previous Update operation? */ + if (sha_info->local) { + i = SHA_BLOCKSIZE - sha_info->local; + if (i > count) { + i = count; + } + inbytes_left = outbytes_left = i; + apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, + ((UINT8 *) sha_info->data) + sha_info->local, + &outbytes_left); + count -= i; + buffer += i; + sha_info->local += i; + if (sha_info->local == SHA_BLOCKSIZE) { + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + else { + return; + } + } + while (count >= SHA_BLOCKSIZE) { + inbytes_left = outbytes_left = SHA_BLOCKSIZE; + apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, + (UINT8 *) sha_info->data, &outbytes_left); + buffer += SHA_BLOCKSIZE; + count -= SHA_BLOCKSIZE; + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + } + inbytes_left = outbytes_left = count; + apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left, + (UINT8 *) sha_info->data, &outbytes_left); + sha_info->local = count; +#else + apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count); +#endif +} + +/* finish computing the SHA digest */ + +APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE], + apr_sha1_ctx_t *sha_info) +{ + int count, i, j; + UINT32 lo_bit_count, hi_bit_count, k; + + lo_bit_count = sha_info->count_lo; + hi_bit_count = sha_info->count_hi; + count = (int) ((lo_bit_count >> 3) & 0x3f); + ((UINT8 *) sha_info->data)[count++] = 0x80; + if (count > SHA_BLOCKSIZE - 8) { + memset(((UINT8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count); + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_transform(sha_info); + memset((UINT8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8); + } + else { + memset(((UINT8 *) sha_info->data) + count, 0, + SHA_BLOCKSIZE - 8 - count); + } + maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE); + sha_info->data[14] = hi_bit_count; + sha_info->data[15] = lo_bit_count; + sha_transform(sha_info); + + for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) { + k = sha_info->digest[i]; + digest[j++] = (unsigned char) ((k >> 24) & 0xff); + digest[j++] = (unsigned char) ((k >> 16) & 0xff); + digest[j++] = (unsigned char) ((k >> 8) & 0xff); + digest[j++] = (unsigned char) (k & 0xff); + } +} + +#if 0 +APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out) +{ + int l; + apr_sha1_ctx_t context; + apr_byte_t digest[APR_SHA1_DIGESTSIZE]; + + apr_sha1_init(&context); + apr_sha1_update(&context, clear, len); + apr_sha1_final(digest, &context); + + /* private marker. */ + apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1); + + /* SHA1 hash is always 20 chars */ + l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest)); + out[l + APR_SHA1PW_IDLEN] = '\0'; + + /* + * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN + */ +} +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/signatureMng/sha256.c b/code/application/source/sf_app/code/source/signatureMng/sha256.c new file mode 100755 index 000000000..51faa143d --- /dev/null +++ b/code/application/source/sf_app/code/source/signatureMng/sha256.c @@ -0,0 +1,331 @@ +#include +#include +#include +#include +#include +#include "sha256.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef lint +/* +static const char rcsid[] = +"$Id: sha256.c 680 2003-07-25 21:57:49Z asaddi $"; +*/ +#endif /* !lint */ + +#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define SIGMA0(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22)) +#define SIGMA1(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25)) +#define sigma0(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ ((x) >> 3)) +#define sigma1(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ ((x) >> 10)) + +#define DO_ROUND() { \ + t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++); \ + t2 = SIGMA0(a) + Maj(a, b, c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + t1; \ + d = c; \ + c = b; \ + b = a; \ + a = t1 + t2; \ +} + +static const UINT32 K[64] = { + 0x428a2f98L, 0x71374491L, 0xb5c0fbcfL, 0xe9b5dba5L, + 0x3956c25bL, 0x59f111f1L, 0x923f82a4L, 0xab1c5ed5L, + 0xd807aa98L, 0x12835b01L, 0x243185beL, 0x550c7dc3L, + 0x72be5d74L, 0x80deb1feL, 0x9bdc06a7L, 0xc19bf174L, + 0xe49b69c1L, 0xefbe4786L, 0x0fc19dc6L, 0x240ca1ccL, + 0x2de92c6fL, 0x4a7484aaL, 0x5cb0a9dcL, 0x76f988daL, + 0x983e5152L, 0xa831c66dL, 0xb00327c8L, 0xbf597fc7L, + 0xc6e00bf3L, 0xd5a79147L, 0x06ca6351L, 0x14292967L, + 0x27b70a85L, 0x2e1b2138L, 0x4d2c6dfcL, 0x53380d13L, + 0x650a7354L, 0x766a0abbL, 0x81c2c92eL, 0x92722c85L, + 0xa2bfe8a1L, 0xa81a664bL, 0xc24b8b70L, 0xc76c51a3L, + 0xd192e819L, 0xd6990624L, 0xf40e3585L, 0x106aa070L, + 0x19a4c116L, 0x1e376c08L, 0x2748774cL, 0x34b0bcb5L, + 0x391c0cb3L, 0x4ed8aa4aL, 0x5b9cca4fL, 0x682e6ff3L, + 0x748f82eeL, 0x78a5636fL, 0x84c87814L, 0x8cc70208L, + 0x90befffaL, 0xa4506cebL, 0xbef9a3f7L, 0xc67178f2L +}; + + +#ifndef RUNTIME_ENDIAN + +#ifdef WORDS_BIGENDIAN + +#define BYTESWAP(x) (x) +#define BYTESWAP64(x) (x) + +#else /* WORDS_BIGENDIAN */ + +#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \ + (ROTL((x), 8) & 0x00ff00ffL)) +#define BYTESWAP64(x) _byteswap64(x) + +//static inline uint64_t _byteswap64(uint64_t x) +unsigned long long _byteswap64(unsigned long long x) +{ + UINT32 a = x >> 32; + UINT32 b = (UINT32) x; + return ((unsigned long long) BYTESWAP(b) << 32) | (unsigned long long) BYTESWAP(a); +} + +#endif /* WORDS_BIGENDIAN */ + +#endif /* !RUNTIME_ENDIAN */ + +static const UINT8 padding[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void +SHA256Init (SHA256Context *sc) +{ +#ifdef RUNTIME_ENDIAN + setEndian (&sc->littleEndian); +#endif /* RUNTIME_ENDIAN */ + + sc->totalLength = 0LL; + sc->hash[0] = 0x6a09e667L; + sc->hash[1] = 0xbb67ae85L; + sc->hash[2] = 0x3c6ef372L; + sc->hash[3] = 0xa54ff53aL; + sc->hash[4] = 0x510e527fL; + sc->hash[5] = 0x9b05688cL; + sc->hash[6] = 0x1f83d9abL; + sc->hash[7] = 0x5be0cd19L; + sc->bufferLength = 0L; +} + +static void +burnStack (int size) +{ + char buf[128]; + + memset (buf, 0, sizeof (buf)); + size -= sizeof (buf); + if (size > 0) + burnStack (size); +} + +static void +SHA256Guts (SHA256Context *sc, const UINT32 *cbuf) +{ + UINT32 buf[64]; + UINT32 *W, *W2, *W7, *W15, *W16; + UINT32 a, b, c, d, e, f, g, h; + UINT32 t1, t2; + const UINT32 *Kp; + int i; + + W = buf; + + for (i = 15; i >= 0; i--) { + *(W++) = BYTESWAP(*cbuf); + cbuf++; + } + + W16 = &buf[0]; + W15 = &buf[1]; + W7 = &buf[9]; + W2 = &buf[14]; + + for (i = 47; i >= 0; i--) { + *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++); + W2++; + W15++; + } + + a = sc->hash[0]; + b = sc->hash[1]; + c = sc->hash[2]; + d = sc->hash[3]; + e = sc->hash[4]; + f = sc->hash[5]; + g = sc->hash[6]; + h = sc->hash[7]; + + Kp = K; + W = buf; + +#ifndef SHA256_UNROLL +#define SHA256_UNROLL 1 +#endif /* !SHA256_UNROLL */ + +#if SHA256_UNROLL == 1 + for (i = 63; i >= 0; i--) + DO_ROUND(); +#elif SHA256_UNROLL == 2 + for (i = 31; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 4 + for (i = 15; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 8 + for (i = 7; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 16 + for (i = 3; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 32 + for (i = 1; i >= 0; i--) { + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + } +#elif SHA256_UNROLL == 64 + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); +#elif SHA256_UNROLL == 68 + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); + DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND(); +#else +#error "SHA256_UNROLL must be 1, 2, 4, 8, 16, 32, or 64!" +#endif + + sc->hash[0] += a; + sc->hash[1] += b; + sc->hash[2] += c; + sc->hash[3] += d; + sc->hash[4] += e; + sc->hash[5] += f; + sc->hash[6] += g; + sc->hash[7] += h; + +} + +void +SHA256Update (SHA256Context *sc, const void *vdata, UINT32 len) +{ + const UINT8 *data = (const UINT8 *)vdata; + UINT32 bufferBytesLeft; + UINT32 bytesToCopy; + int needBurn = 0; + +#ifdef SHA256_FAST_COPY +#else /* SHA256_FAST_COPY */ + while (len) + { + bufferBytesLeft = 64L - sc->bufferLength; + + bytesToCopy = bufferBytesLeft; + if (bytesToCopy > len) + bytesToCopy = len; + + memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy); + + sc->totalLength += bytesToCopy * 8L; + + sc->bufferLength += bytesToCopy; + data += bytesToCopy; + len -= bytesToCopy; + + if (sc->bufferLength == 64L) { + SHA256Guts (sc, sc->buffer.words); + needBurn = 1; + sc->bufferLength = 0L; + } + } +#endif /* SHA256_FAST_COPY */ + + if (needBurn) + burnStack (sizeof (UINT32[74]) + sizeof (UINT32 *[6]) + sizeof (int)); +} + +void +SHA256Final (SHA256Context *sc, UINT8 hash[SHA256_HASH_SIZE]) +{ + UINT32 bytesToPad; + unsigned long long lengthPad; + int i; + + bytesToPad = 120L - sc->bufferLength; + if (bytesToPad > 64L) + bytesToPad -= 64L; + + lengthPad = BYTESWAP64(sc->totalLength); + + SHA256Update (sc, padding, bytesToPad); + SHA256Update (sc, &lengthPad, 8L); + + if (hash) { + for (i = 0; i < SHA256_HASH_WORDS; i++) { +#ifdef SHA256_FAST_COPY + *((UINT32 *) hash) = BYTESWAP(sc->hash[i]); +#else /* SHA256_FAST_COPY */ + hash[0] = (UINT8) (sc->hash[i] >> 24); + hash[1] = (UINT8) (sc->hash[i] >> 16); + hash[2] = (UINT8) (sc->hash[i] >> 8); + hash[3] = (UINT8) sc->hash[i]; +#endif /* SHA256_FAST_COPY */ + hash += 4; + + } + } +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/code/application/source/sf_app/code/source/storeMng/sf_storeMng.c b/code/application/source/sf_app/code/source/storeMng/sf_storeMng.c new file mode 100755 index 000000000..a50775ece --- /dev/null +++ b/code/application/source/sf_app/code/source/storeMng/sf_storeMng.c @@ -0,0 +1,390 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" +#include "sf_fileMng.h" +#include "sf_storeMng.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +static SF_SD_STATUS_E SdStatus = SF_SD_BUTT; + +static SINT32 sd_file_Isexsit(SF_CHAR *fileName) +{ + return access(fileName, F_OK); +} + +static SINT32 sd_Isdirempty(char *dirname) +{ + SF_COMM_CHECK_POINTER(dirname,SF_FAILURE); + + DIR *dir = opendir(dirname); + if (dir == NULL) + { + perror("seekkey.c-98-opendir"); + return SF_FAILURE; + } + + while (1) + { + struct dirent *ent; + ent = readdir (dir); + if (ent <= 0) + { + break; + } + if ((strcmp(".", ent->d_name)==0) || (strcmp("..", ent->d_name)==0)) + { + continue; + } + /*adjust include file or dir*/ + if ((ent->d_type == DT_DIR) || (ent->d_type == DT_REG)) + { + closedir(dir); + return SF_FAILURE; + } + } + closedir(dir); + return SF_SUCCESS; +} + +SINT32 sf_sd_info_get(SF_STORE_ATTR_S *pstoreattrs) +{ + SF_COMM_CHECK_POINTER(pstoreattrs,SF_FAILURE); + + SINT32 fd = -1; + fd = open(SF_SD_ROOT, O_RDONLY,0); + if(fd >= 0) + { + struct statfs diskInfo; + statfs(SF_SD_ROOT, &diskInfo); + + if(diskInfo.f_bsize > 1024) + { + pstoreattrs->SDTotalSize = (diskInfo.f_blocks * (diskInfo.f_bsize >> 10)) >> 10 ; //blocks * 4096 / 1024 /1024 = MB + pstoreattrs->SDFree = (diskInfo.f_bavail * (diskInfo.f_bsize >> 10)) >> 10 ; + } + else + { + pstoreattrs->SDTotalSize = (diskInfo.f_blocks * diskInfo.f_bsize) >> 10 ; //blocks * 4096 / 1024 /1024 = MB + pstoreattrs->SDFree = (diskInfo.f_bavail * diskInfo.f_bsize) >> 10 ; + } + close(fd); + + if(pstoreattrs->SDTotalSize > 0) + pstoreattrs->SDStatus = 0; //SD card SUCESS + else + pstoreattrs->SDStatus = 2; //SD card ERROR + } + else + { + pstoreattrs->SDStatus = 1; //SD card not insert + pstoreattrs->SDFree = 0; + pstoreattrs->SDTotalSize = 0; + return SF_FAILURE; + } + + MLOGD("SDStatus = %d,SDFree = %d MB,SDTotalSize = %d MB\n", pstoreattrs->SDStatus, pstoreattrs->SDFree,pstoreattrs->SDTotalSize); + return SF_SUCCESS; +} + +SINT32 sf_sd_isfull(SINT8 *Isfull) +{ + SF_STORE_ATTR_S storeattrs = {0}; + sf_sd_info_get(&storeattrs); + if(storeattrs.SDStatus != 0) + return storeattrs.SDStatus; + + *Isfull = (storeattrs.SDFree <= SD_WARNING_SPACE)?1:0; + return SF_SUCCESS; +} +SINT32 sf_sd_remove_file(const char *path,SINT32 threshold) +{ + SF_COMM_CHECK_POINTER(path,SF_FAILURE); + if(SF_SUCCESS != sd_file_Isexsit(path)) { + MLOGD("%s is empty!!!\n",path); + return SF_SUCCESS; + } + + SINT32 s32ret = SF_SUCCESS; + SINT32 index = 0; + SINT32 fileCnt = 0; + SINT32 totalFile = 0; + SF_CHAR fileabspath[FILENAMELEN] = {0}; + struct dirent **namelist; + + totalFile = scandir(path,&namelist,0,alphasort); + if(totalFile< 0) { + SLOGE("open [%s] error!!!\n",path); + return -1; + } + + while(index < totalFile) { +// MLOGD("d_name: %s\n",namelist[index]->d_name); + if(strcmp(namelist[index]->d_name, ".") == 0 || strcmp(namelist[index]->d_name, "..") == 0) { + index++; + continue; + } + sprintf(fileabspath, "%s/%.32s", path,namelist[index]->d_name); + if(!(strstr(fileabspath, SF_DCF_EXT_MOV) || strstr(fileabspath, SF_DCF_EXT_PHOTO))) { + index++; + continue; + } + if(SF_SUCCESS != sd_file_Isexsit(fileabspath)) { + index++; + continue; + } + s32ret = sf_file_remove(fileabspath); + if(SF_SUCCESS != s32ret) { + index++; + continue; + } + + index++; + fileCnt++; + + if(threshold <= 0) + continue; + + if(fileCnt > threshold) + break; + } + return SF_SUCCESS; +} + +SINT32 sf_sd_loopremove(const char *path) +{ + SF_COMM_CHECK_POINTER(path,SF_FAILURE); + int dircnt; + int index=0; + char strdirTmp[FILENAMELEN] = {0}; + char cPathTmp[FILENAMELEN] = {0}; + char cFileTmp[FILENAMELEN] = {0}; + + char g_cFileList[FILETXTCNT][FILENAMELEN] = {0}; + + int FileCount = 0; + char filedir[4] = {0}; + char filenum[6] = {0}; + char filetype[4] = {0}; + char fname[FILENAMELEN] = {0}; + char *pTemp = NULL; + + DIR *dirsub = SF_NULL; + struct dirent *entrysub = SF_NULL; + struct dirent **namelist; + + SF_STORE_ATTR_S storeattrs = {0}; + UINT32 oldsdFree = 0; + UINT8 sdcnt = 0; + dircnt = scandir(path,&namelist,0,alphasort); + if(dircnt< 0) + { + SLOGE("open [%s] error!!!\n",path); + return -1; + } + + while(index < dircnt) + { + MLOGD("d_name: %s\n",namelist[index]->d_name); + if(strcmp(namelist[index]->d_name, ".") == 0 || strcmp(namelist[index]->d_name, "..") == 0) { + index++; + continue; + } + + memset(strdirTmp, '\0', FILENAMELEN); + strcpy(strdirTmp, namelist[index]->d_name); + /*filter not xxxSYCAM dir*/ + if(!strstr(strdirTmp, SF_DCF_DIR_NAME_SUFFIX)) { + index++; + continue; + } + + /*Empty Dir, Delete it.*/ + sprintf(cPathTmp, "%s/%.32s", path,namelist[index]->d_name); + if(sd_Isdirempty(cPathTmp) == 0) + { + sf_file_remove(cPathTmp); + MLOGD("%s is empty,has removed !!!\n",cPathTmp); + index++; + continue; + } + + /*open subDir*/ + MLOGD("%s\n",cPathTmp); + dirsub = opendir(cPathTmp); + if (dirsub == NULL) { + MLOGE("opendir [%s] error!!!\n", cPathTmp); + index++; + continue; + } + + while((entrysub = readdir(dirsub))) + { + + /*Jump . or .. dir*/ + if(strcmp(entrysub->d_name, ".") == 0 || strcmp(entrysub->d_name, "..") == 0) + continue; + + /*Not Empty , Record File Name*/ + sprintf(cFileTmp, "%.64s/%.32s", cPathTmp, entrysub->d_name); + + + strcpy(g_cFileList[FileCount], cFileTmp); + if(SF_NULL != g_cFileList[FileCount]) + { + + pTemp = strstr(g_cFileList[FileCount], SF_DCF_DIR_NAME_SUFFIX); + if(pTemp) + { + pTemp = pTemp - 3; + + filedir[0] = *pTemp++; + filedir[1] = *pTemp++; + filedir[2] = *pTemp++; /*get file group ID*/ + filedir[3] = '\0'; + + pTemp = strstr(g_cFileList[FileCount], SF_DCF_FILE_NAME_PREFIX); + + if(pTemp) + { + pTemp = pTemp + 4; + + filenum[0] = *pTemp++; + filenum[1] = *pTemp++; + filenum[2] = *pTemp++; + filenum[3] = *pTemp++; /* get file ID Added by MaxLi 2022/03/21--13:49:22*/ + filenum[4] = '\0'; + pTemp++; + filetype[0] = *pTemp++; + filetype[1] = *pTemp++; + filetype[2] = *pTemp++; /* get file type Added by MaxLi 2022/03/21--13:49:45*/ + filetype[3] = '\0'; + + if(strstr(filetype, SF_DCF_EXT_MOV)) + { + sprintf(fname, "%sW%s%s.JPG",SF_4G_PIC_THUMB_PATH, filedir, filenum); + if(SF_SUCCESS == sd_file_Isexsit(fname)) + { + sf_file_remove(fname); + MLOGD("Will Delete video sub File Name:%s\n", fname); + } + sprintf(fname, "%sS%s%s.MP4", SF_4G_SMALL_VIDEO_STREAM_PATH,filedir, filenum); + if(SF_SUCCESS == sd_file_Isexsit(fname)) + { + sf_file_remove(fname); + MLOGD("Will Delete smallstream File Name:%s\n", fname); + } + + MLOGD("Will Delete mainstream File Name:%s\n", g_cFileList[FileCount]); + sf_file_remove(g_cFileList[FileCount]); + + + } + else if(strstr(filetype, SF_DCF_EXT_PHOTO)) + { + sprintf(fname, "%sW%s%s.JPG",SF_4G_PIC_THUMB_PATH, filedir, filenum); + if(SF_SUCCESS == sd_file_Isexsit(fname)) + { + sf_file_remove(fname); + MLOGD("Will Delete thumb pic File Name:%s\n", fname); + } + MLOGD("Will Delete initial pic File Name:%s\n", g_cFileList[FileCount]); + sf_file_remove(g_cFileList[FileCount]); + } + } + } + + } + + FileCount++; + if(FileCount % 20 == 0) + { + sf_sd_info_get(&storeattrs); + MLOGD("sdFree=%d,oldsdFree=%d\n",storeattrs.SDFree ,oldsdFree); + if(storeattrs.SDFree != oldsdFree) + { + sdcnt = 0; + oldsdFree = storeattrs.SDFree; + } + else + { + sdcnt++; + if(sdcnt>3) + { + sdcnt = 0; + closedir(dirsub); + free(namelist[index]); + free(namelist); + return SF_FAILURE; + + } + } + if(storeattrs.SDFree > (SDLOOP_REMAIN_SPACE+50)) + { + FileCount = FILETXTCNT; + break; + } + else + { + //if del 300 files, sd free size < 350, del file + if(FileCount >= FILETXTCNT) + { + FileCount = 0; + } + } + } + + } + + closedir(dirsub); + free(namelist[index]); + index++;//index++ + + if(FileCount >=FILETXTCNT) + break; + + } + free(namelist); + return 0; + +} + + +SF_SD_STATUS_E sf_sd_status_get(void) +{ + MLOGI("SdStatus:%d\n", SdStatus); + return SdStatus; +} + +SINT32 sf_sd_status_set(SF_SD_STATUS_E enStatus) +{ + SF_STORE_CHECK_RANGE(enStatus ,SF_SD_OUT, SF_SD_BUTT); + SdStatus = enStatus; + + MLOGI("SdStatus:%d\n", SdStatus); + return SF_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/systemMng/sf_commu_mcu.c b/code/application/source/sf_app/code/source/systemMng/sf_commu_mcu.c new file mode 100755 index 000000000..52af270d8 --- /dev/null +++ b/code/application/source/sf_app/code/source/systemMng/sf_commu_mcu.c @@ -0,0 +1,1028 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: ljy + * Ver: 1.0.0 2022.06.15 + * Description: creat +**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sf_type.h" +#include "sf_log.h" +#include "sf_keymng.h" +#include "sf_message_queue.h" +#include "sf_commu_mcu.h" + +#define SERIAL_DEVICE_PATH "/dev/ttyS2" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +unsigned char mcu_upgrade_buf[32]; +unsigned char mcu_upgrade_buf_len; + +static const unsigned short Crc16Table[256] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +/************************************************* + Function: sf_crc16_check + Description: crc16 check + Input: data, data len + Output: N/A + Return: crc16 value + Others: N/A +*************************************************/ + +static unsigned short sf_crc16_check(unsigned char * dataIn, int length) +{ + unsigned short result = 0; + unsigned short tableNo = 0; + + for (int i = 0; i < length; i++) + { + tableNo = ((result & 0xff) ^ (dataIn[i] &0xff)); + result = ((result >> 8) & 0xff) ^Crc16Table[tableNo]; + } + + return result; +} + +static unsigned char sndBuf[BUF_REG_SIZE] = +{ + 0 +}; + +SMAPBUF_t smap_buf = +{ + .index = 0, +}; + +int SMAP_waitAck = 0; + +unsigned char mcu_buf[BUF_REG_SIZE] = {0}; +unsigned int mcu_buf_len = 0; +unsigned char cmpRegBuf[BUF_REG_SIZE] = {0}; +unsigned char cmpValBuf[BUF_REG_SIZE] = {0}; + +static unsigned char sf_commu_mcu_exit = 1; +static pthread_t sfCommuMcuThread = 0; +static void * sf_commu_mcu_task(void * argv); + +int gsfd = -1; + +void mcubuf_reset(void) +{ + mcu_buf_len = 0; + memset(mcu_buf, 0x00, sizeof(mcu_buf)); +} + + +int sf_commu_mcu_open(void) +{ + int ret = -1; + gsfd = open(SERIAL_DEVICE_PATH, O_RDWR); + if(gsfd < 0) + { + printf("Open %s error!\n", SERIAL_DEVICE_PATH); + ret = -1; + return ret; + } + else + { + printf("Open %s success!\n", SERIAL_DEVICE_PATH); + } + return 0; +} + +int sf_commu_mcu_close(void) +{ + if(gsfd > 0) + close(gsfd); + return 0; +} + + + +int sf_commu_mcu_interface_init(int speed, char flow_ctrl, int databits, int stopbits, char parity) +{ + + int i; + int speed_arr[] = {B115200, B460800}; + int name_arr[] = {115200, 460800}; + struct termios options; + int fd = -1; + int ret = -1; + fd = open(SERIAL_DEVICE_PATH, O_RDWR); + if(fd < 0) + { + printf("Open %s error!\n", SERIAL_DEVICE_PATH); + ret = -1; + return ret; + } + else + { + printf("Open %s success!\n", SERIAL_DEVICE_PATH); + } + + if(tcgetattr(fd,&options) != 0) + { + printf("SetupSerial 1"); + close(fd); + return -1; + } + + //cfmakeraw(&options); + + for (i= 0; i < (2); i++) + { + if(speed == name_arr[i]) + { + cfsetispeed(&options, speed_arr[i]); + cfsetospeed(&options, speed_arr[i]); + } + } +#if 1 + //options.c_cflag |= CLOCAL; + //options.c_cflag |= CREAD; + + switch(flow_ctrl) + { + case 'n': + case 'N'://不使用流控制 + options.c_cflag &= ~(600);//CRTSCTS; + break; + + case 'h': + case 'H'://使用硬件流控制 + options.c_cflag |= 600;//CRTSCTS; + break; + + case 'S': + case 's'://使用软件流控制 + options.c_cflag |= IXON | IXOFF | IXANY; + break; + } + + //设置数据位 + options.c_cflag &= ~CSIZE; //屏蔽其他标志位 + + switch (databits) + { + case 5: + options.c_cflag |= CS5; + break; + + case 6: + options.c_cflag |= CS6; + break; + + case 7: + options.c_cflag |= CS7; + break; + + case 8: + options.c_cflag |= CS8; + break; + + default: + printf("Unsupported data size/n"); + close(fd); + return -1; + } + + //设置校验位 + switch (parity) + { + case 'n': + case 'N': //无奇偶校验位 + options.c_cflag &= ~PARENB; + options.c_iflag &= ~INPCK; + break; + + case 'o': + case 'O'://设置为奇校验 + options.c_cflag |= (PARODD | PARENB); + options.c_iflag |= INPCK; + break; + + case 'e': + case 'E'://设置为偶校验 + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + options.c_iflag |= INPCK; + break; + + case 's': + case 'S': //设置为空格 + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + break; + + default: + printf("Unsupported parity/n"); + close(fd); + return -1; + } + + // 设置停止位 + switch (stopbits) + { + case 1: + options.c_cflag &= ~CSTOPB; + break; + + case 2: + options.c_cflag |= CSTOPB; + break; + + default: + printf("Unsupported stop bits/n"); + close(fd); + return -1; + } + + //修改输出模式,原始数据输出 + options.c_oflag &= ~OPOST; + + //激活配置 (将修改后的termios数据设置到串口中) + if (tcsetattr(fd,TCSANOW,&options) != 0) + { + printf("com set error!/n"); + close(fd); + return -1; + } + + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG ); + options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + + //设置等待时间和最小接收字符 + options.c_cc[VTIME] = 0; + options.c_cc[VMIN] = 1; + + //如果发生数据溢出,接收数据,但是不再读取 + tcflush(fd,TCIFLUSH); +#endif + + //激活配置 (将修改后的termios数据设置到串口中) + if (tcsetattr(fd,TCSANOW,&options) != 0) + { + printf("com set error!/n"); + close(fd); + return -1; + } + close(fd); + return 0; +} + +int sf_commu_write(unsigned char * buf, int len) +{ + int ret = SF_FAILURE; + + ret = write(gsfd, buf, len); + if(ret < 0) + { + MLOGI("%s write error!\n", SERIAL_DEVICE_PATH); + close(gsfd); + return SF_FAILURE; + } + return ret; +} + + +int sf_commu_read(unsigned char * buf, int len) +{ + int ret = SF_SUCCESS; + ret = read(gsfd, buf, len); + if(ret < 0) + return SF_FAILURE; + return ret; + +} + +int sf_set_mcu_reg(unsigned char reg, unsigned char val) +{ + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + int ret = FAIL; + memset(sndBuf, 0x00, sizeof(sndBuf)); + // uint8_t i = 0; + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x03; + index++; + sndBuf[index] = reg; + index++; + sndBuf[index] = val; + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + ret = sf_commu_write(sndBuf, index + 1); + if(ret == FAIL) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + } + return 0x03; +} + +int sf_get_mcu_reg(unsigned char reg) +{ + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + int ret = FAIL; + //uint8_t i = 0; + memset(sndBuf, 0x00, sizeof(sndBuf)); + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x01; + index++; + sndBuf[index] = reg; + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + + ret = sf_commu_write(sndBuf, index + 1); + if(ret == FAIL) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + } + + return 0x01; +} + +int sf_set_mcu_reg_many(unsigned char reg[], unsigned char val[], unsigned int num) +{ + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + unsigned int i = 0; + int ret = FAIL; + memset(sndBuf, 0x00, sizeof(sndBuf)); + // uint8_t i = 0; + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x04; + index++; + sndBuf[index] = num; + + for(i = 0; i < num; i++) + { + index++; + sndBuf[index] = reg[i]; + index++; + sndBuf[index] = val[i]; + + } + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + ret = sf_commu_write(sndBuf, index + 1); + if(ret == FAIL) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + } + return 0x03; +} + +int sf_get_mcu_reg_many(unsigned char reg[], unsigned int num) +{ + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + unsigned int i = 0; + int ret = FAIL; + //uint8_t i = 0; + memset(sndBuf, 0x00, sizeof(sndBuf)); + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x02; + index++; + sndBuf[index] = num; + + + for(i = 0; i < num; i++) + { + index++; + sndBuf[index] = reg[i]; + } + + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + + ret = sf_commu_write(sndBuf, index + 1); + if(ret == FAIL) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + } + + return 0x01; +} + +unsigned int sf_set_mcu_reg_ack_depack(unsigned int * address, unsigned int * value) +{ + unsigned short crc1 = (((unsigned short) smap_buf.buf[smap_buf.index - 4]) << 8) | smap_buf.buf[smap_buf.index - 3]; + unsigned short crc2 = 0; + + crc2 = sf_crc16_check(&smap_buf.buf[2], smap_buf.index - 6); + + if (crc2 != crc1) + { + printf("crc error crc1 %d, crc2 %d, function %s\r\n", crc1, crc2, __FUNCTION__); + return - 1; + } + + *address = smap_buf.buf[3]; + *value = smap_buf.buf[4]; + + if (smap_buf.buf[2] == 0xFF) /* error command 0xff */ + { + printf("%s:%d command error\r\n", __FUNCTION__, __LINE__); + return - 1; + } + + return (unsigned int)smap_buf.buf[2]; +} + +unsigned int sf_get_mcu_reg_ack_depack(unsigned int * address, unsigned int * value) +{ + unsigned short crc1 = (((unsigned short) smap_buf.buf[smap_buf.index - 4] << 8) & 0xff00) | smap_buf.buf[smap_buf.index - 3]; + unsigned short crc2 = 0; + + crc2 = sf_crc16_check(&smap_buf.buf[2], smap_buf.index - 6); + + if (crc2 != crc1) + { + printf("crc error crc1 %d, crc2 %d, function %s, file %s, line %d\r\n", crc1, crc2, __FUNCTION__, + __FILE__, __LINE__); + return - 1; + } + + *address = smap_buf.buf[3]; + *value = smap_buf.buf[4]; + + if (smap_buf.buf[2] == 0xFF) /* error command 0xff */ + { + printf("%s:%d command error\r\n", __FUNCTION__, __LINE__); + return - 1; + } + + return (unsigned int)smap_buf.buf[2]; +} + + + +unsigned int sf_get_mcu_reg_ack_depack_many(unsigned char reg[], unsigned char val[], unsigned int * num) +{ + unsigned short crc1 = (((unsigned short) smap_buf.buf[smap_buf.index - 4] << 8) & 0xff00) | smap_buf.buf[smap_buf.index - 3]; + unsigned short crc2 = 0; + unsigned int i = 0; + unsigned int j = 4; + + crc2 = sf_crc16_check(&smap_buf.buf[2], smap_buf.index - 6); + + if (crc2 != crc1) + { + printf("crc error crc1 %d, crc2 %d, function %s, file %s, line %d\r\n", crc1, crc2, __FUNCTION__, + __FILE__, __LINE__); + return - 1; + } + *num = smap_buf.buf[3]; + + for(i = 0; i < *num; i++) + { + reg[i]= smap_buf.buf[j]; + j++; + val[i]= smap_buf.buf[j]; + j++; + } + + if (smap_buf.buf[2] == 0xFF) /* error command 0xff */ + { + printf("%s:%d command error\r\n", __FUNCTION__, __LINE__); + return - 1; + } + + return (unsigned int)smap_buf.buf[2]; +} + +int sf_commu_wait(unsigned char cmd) +{ + volatile char trytimes = 0; + while ((smap_buf.buf[2] != cmd || SMAP_waitAck == 0) && trytimes <= 100) + { + trytimes++; + usleep(10000); + } + if (trytimes > 100) + { + sf_commu_reset(); + return - 1; + } + return 0; +} + +void sf_commu_reset(void) +{ + smap_buf.index = 0; + SMAP_waitAck = 0; + memset(smap_buf.buf, 0x00, sizeof(smap_buf.buf)); + memset(cmpRegBuf, 0x00, sizeof(cmpRegBuf)); + memset(cmpValBuf, 0x00, sizeof(cmpValBuf)); +} + +int sf_commu_set_mcu(unsigned char reg, unsigned char val) +{ + int ret = -1; + unsigned int address = 0; + unsigned int value = 0; + //printf("W_addr[%02d,0x%02x]\n", reg,val); + sf_commu_reset(); + sf_set_mcu_reg(reg, val); + ret = sf_commu_wait(0x03); + if(ret < 0) + { + printf("%s:%d time out\r\n", __FUNCTION__, __LINE__); + sf_commu_reset(); + return - 1; + } + ret = sf_set_mcu_reg_ack_depack(&address, &value); + + if (ret < 0 || address != reg || value != val) + { + printf("%s:%d error address %d, value %d\r\n", __FUNCTION__, __LINE__, address, value); + ret = -1; + } + else + { + ret = 0; + } + return ret; +} + +int sf_commu_get_mcu(unsigned char reg) +{ + int ret = 0; + unsigned int address = 0; + unsigned int value = 0; + + sf_commu_reset(); + sf_get_mcu_reg(reg); + ret = sf_commu_wait(0x01); + if(ret < 0) + { + printf("%s:%d time out\r\n", __FUNCTION__, __LINE__); + sf_commu_reset(); + return - 1; + } + + ret = sf_get_mcu_reg_ack_depack(&address, &value); + if (ret < 0 || address != reg) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + ret = -1; + } + else + { + ret = (int)value; + } + + return ret; +} +int sf_commu_set_mcu_many(unsigned char reg[], unsigned char val[], unsigned int *num) +{ + int ret = -1; + //unsigned int address = 0; + //unsigned int value = 0; + unsigned int i = 0; + //printf("W_addr[%02d,0x%02x]\n", reg,val); + sf_commu_reset(); + sf_set_mcu_reg_many(reg, val, *num); + ret = sf_commu_wait(0x04); + if(ret < 0) + { + printf("%s:%d time out\r\n", __FUNCTION__, __LINE__); + sf_commu_reset(); + return - 1; + } + + ret = sf_get_mcu_reg_ack_depack_many(cmpRegBuf, cmpValBuf, num); + if (ret < 0) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + ret = -1; + } + else + { + for(i = 0; i < *num; i++) + { + if((reg[i] != cmpRegBuf[i]) || (val[i] != cmpValBuf[i])) + { + printf("%s:%d error address %d, value %d get address %d, value %d\r\n", __FUNCTION__, __LINE__, reg[i], val[i], cmpRegBuf[i], cmpValBuf[i]); + ret = -1; + } + } + } + + return ret; +} + +int sf_commu_get_mcu_many(unsigned char reg[], unsigned char val[], unsigned int *num) +{ + int ret = 0; + unsigned int i = 0; + + sf_commu_reset(); + sf_get_mcu_reg_many(reg,*num); + ret = sf_commu_wait(0x02); + if(ret < 0) + { + printf("%s:%d time out\r\n", __FUNCTION__, __LINE__); + sf_commu_reset(); + return - 1; + } + + ret = sf_get_mcu_reg_ack_depack_many(cmpRegBuf, val, num); + if (ret < 0) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + ret = -1; + } + else + { + for(i = 0; i < *num; i++) + { + if(reg[i] != cmpRegBuf[i]) + { + printf("%s:%d error\r\n", __FUNCTION__, __LINE__); + ret = -1; + } + } + } + + return ret; +} + +int sf_getRegFromMcu_depack(unsigned char * dataToParse, unsigned int datalen, unsigned char * regAddr, unsigned char * regVal) +{ + unsigned short crc1 = 0; + unsigned short crc2 = 0; + unsigned char crc_start = 0; + unsigned char crc_end = 0; + + crc_start = 2; + crc_end = datalen - 4 - 1; + crc1 = (((unsigned short) dataToParse[datalen - 1 - 3] << 8) & 0xff00) | dataToParse[datalen - 1 - 2]; + crc2 = sf_crc16_check(&dataToParse[crc_start], crc_end - crc_start + 1); + + if (crc1 != crc2) + { + printf("0x05 crc error\r\n"); + return - 1; + } + else + { + *regVal = dataToParse[4]; + *regAddr = dataToParse[3]; + return dataToParse[2]; + } +} + +int sf_getRegFromMcu_ack(unsigned char regAddr, unsigned char regVal) +{ + unsigned short index = 0; + unsigned short crc = 0; + unsigned short crc_start = 0; + unsigned short crc_end = 0; + memset(sndBuf, 0x00, sizeof(sndBuf)); + + sndBuf[index] = 0x55; + index++; + sndBuf[index] = 0xAA; + index++; + crc_start = index; + sndBuf[index] = 0x05; + index++; + sndBuf[index] = regAddr; + index++; + sndBuf[index] = regVal; + index++; + crc_end = index; + crc = sf_crc16_check(&sndBuf[crc_start], crc_end - crc_start); + sndBuf[index] = (crc & 0xff00) >> 8; + index++; + sndBuf[index] = crc & 0x00ff; + index++; + sndBuf[index] = 0xFF; + index++; + sndBuf[index] = 0xEE; + + sf_commu_write(sndBuf, index + 1); + + return 0x05; +} + +unsigned char sf_commu_parse_mcu_data(unsigned char * src, unsigned int len) +{ + unsigned char * copyBuf = src; + unsigned int copyLen = len; + int ret = -1; + unsigned char reg[3] = {0}; + unsigned char val[3] = {0}; + + switch (copyBuf[2]) + { + case 0x05: + ret = sf_getRegFromMcu_depack(copyBuf, copyLen, ®[0], &val[0]); + if (ret > 0) + { + MLOGD("MCU send 0x05, reg_value[%d,%d]\n\n",reg[0], val[0]); + sf_getRegFromMcu_ack(reg[0], val[0]); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = CMD_KEY; + stMessageBuf.arg1 = SF_EVENT_KEY_SHORT_CLICK; + stMessageBuf.arg2 = SF_KEY_PIN_DATAREADY; + sf_com_message_send_to_app(&stMessageBuf); + ret = 0x05; + } + else + { + printf("0x05 error\r\n"); + } + break; + /* + case 0x06: + printf("SMAP_parse_data 0x06\r\n"); + ret = SMAP_getMultiRegFromMcu_depack(copyBuf, copyLen, ®Cnt, reg, val); + if (ret > 0) + { + SMAP_getMultiRegFromMcu_ack(regCnt, reg, val); + ret = 0x06; + } + else + { + printf("0x06 error\r\n"); + } + break; + */ + default: + //ret = 0x00; + break; + } + return ret; +} + + +static void * sf_commu_mcu_task(void * argv) +{ + static unsigned char buffer[BUF_REG_SIZE] = {0}; + int i = 0; + int readLen = 0; + int len = 0; + short start = -1; + short end = -1; + unsigned char temp_start1 = 0; + unsigned char temp_start2 = 0; + unsigned char temp_end1 = 0; + unsigned char temp_end2 = 0; + unsigned char copy_size = 0; + sf_commu_mcu_interface_init(115200, 'N', 8, 1, 'N'); + sf_commu_mcu_open(); + mcubuf_reset(); + while(sf_commu_mcu_exit == 0) + { + readLen = sf_commu_read(buffer + len, BUF_REG_SIZE); + + if(readLen > 0) + { + len += readLen; + } + + while(i < len) + { + + while(i < len && start < 0) + { + if(buffer[i] == 0x55) + { + temp_start1 = i; + } + if(buffer[i] == 0xAA) + { + temp_start2 = i; + } + if((temp_start2 - temp_start1) == 1) + { + start = temp_start1; + temp_start1 = 0; + temp_start2 = 0; + break; + } + i++; + } + + + if(start >= 0) + { + while (i < len) + { + if(buffer[i] == 0xFF) + { + temp_end1 = i; + } + if(buffer[i] == 0xEE) + { + temp_end2 = i; + } + if((temp_end2 - temp_end1) == 1) + { + end = temp_end2; + temp_end1 = 0; + temp_end2 = 0; + break; + } + i++; + } + } + + if(start >= 0 && end > 0) + { + copy_size = end - start + 1; + if(buffer[start + 2] != 0xff) + { + if(buffer[start + 2] != 0x05 && buffer[start + 2] != 0x06 && buffer[start + 2] != 0xff) + { + if(buffer[start + 2] == 0xee || buffer[start + 2] == 0xef || buffer[start + 2] == 0xec) + { + memcpy(mcu_upgrade_buf, &buffer[start], copy_size); + mcu_upgrade_buf_len = copy_size; + } + else + { + memcpy(smap_buf.buf + smap_buf.index, &buffer[start], copy_size); + smap_buf.index += copy_size; //index从0开始 + SMAP_waitAck = 1; + } + + } + else + { + memcpy(mcu_buf, &buffer[start], copy_size); + mcu_buf_len = copy_size; + sf_commu_parse_mcu_data(mcu_buf, mcu_buf_len); + mcubuf_reset(); + } + start = -1; + end = -1; + len = 0; + i = 0; + + } + else + { + start = -1; + end = -1; + len = 0; + i = 0; + } + } + } + + usleep(10000);//10ms + } + pthread_exit(0); +} + + + +void sf_commu_mcu_task_start(void) +{ + if(sf_commu_mcu_exit == 1) + { + pthread_create(&sfCommuMcuThread, NULL, sf_commu_mcu_task, NULL); + sf_commu_mcu_exit = 0; + } +} + + +void sf_commu_mcu_task_stop(void) +{ + sf_commu_mcu_exit = 1; + pthread_join(sfCommuMcuThread, NULL); +} + +unsigned char sf_commu_mcu_task_running(void) +{ + return sf_commu_mcu_exit; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/systemMng/sf_commu_mcu_reg.c b/code/application/source/sf_app/code/source/systemMng/sf_commu_mcu_reg.c new file mode 100755 index 000000000..14bb07255 --- /dev/null +++ b/code/application/source/sf_app/code/source/systemMng/sf_commu_mcu_reg.c @@ -0,0 +1,900 @@ + +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: ljy + * Ver: 1.0.0 2020.06.20 + * Description: created + * +**************************************************************************/ +#include +#include +#include "sf_log.h" + +#include +#include +#include "sf_commu_mcu.h" +#include "sf_commu_mcu_reg.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +unsigned char GPRSPOWER = 0; +static unsigned char McuSubVersion = 0; +static unsigned short McuVersion = 0; +static unsigned char McuProductInfo = 0; + +unsigned char McuPowerOnMode = 0;//=>PWR_ON_SETUP +unsigned char CameraMode = 0; //bit0~3:1 Picture,2 Video,3 TimeLapse,4 PIC+video; bit7:0 fast capture. bit7:1 Normal capture +unsigned char IrLedPercent = 0; +unsigned char McuBatMode = 0; +unsigned short IRSHTTER = 0; +unsigned short TrigType = 0; +unsigned int powerSave_t1 = 0; +unsigned char DailyReportStartMode = 0; +unsigned char POWEROFF = 0; +SF_TIME_S sfMcuTime = { 0 }; + +UINT8 sf_mcu_read(UINT32 reg, UINT8 *data) +{ + *data = sf_commu_get_mcu(reg); + printf("R_addr[%d]=0x%02x\n", reg, *data); + return 0; +} + +UINT8 sf_mcu_write(UINT32 reg, UINT32 data) +{ + sf_commu_set_mcu(reg, data); + printf("W_addr[%d]=0x%02x\n", reg, data); + return 0; +} +int sf_mcu_init(void) +{ + sf_commu_mcu_task_start(); + return 0; +} +UINT8 sf_mcu_write_multi(UINT8 reg[], UINT8 data[], UINT32 num) +{ + UINT32 i; + unsigned int pnum = num; + if(0 <= sf_commu_set_mcu_many(reg, data, &pnum)) + { + for(i = 0; i < num; i++) + { + printf("W_addr[%d]=0x%02x\n", reg[i], data[i]); + } + return SUCCESS; + } + return FAIL; +} + +UINT8 sf_mcu_read_multi(UINT8 reg[], UINT8 data[], UINT32 num) +{ + UINT32 i; + unsigned int pnum = num; + if(0 <= sf_commu_get_mcu_many(reg, data, &pnum)) + { + for(i = 0; i < num; i++) + { + printf("R_addr[%d]=0x%02x\n", reg[i], data[i]); + } + return SUCCESS; + } + return FAIL; +} + +/************************************************* + Function: sf_mcu_power_on_para_get + Description: read MCU register data to update uipara and variable. + Input: attrId:which kind of para want to get + Output: N/A + Return: start mode + Others: N/A +*************************************************/ +unsigned char sf_mcu_power_on_para_get (MCUParam_t attrId) +{ + unsigned char dataTemp1 = 0, dataTemp2 = 0; + unsigned char startMode = 0; + //unsigned char mcuVer = 0; + unsigned char mcuReg[REG_SIZE] = { 0 }; + unsigned char mcuData[REG_SIZE] = { 0 }; + unsigned char i = 0; + + if(attrId == SF_MCU_STARTMODE) + { + sf_mcu_read(START_MODE, &dataTemp1); + startMode = dataTemp1 & 0x1F; + } + else + { + mcuReg[i++] = MCU_SUB_VER; + mcuReg[i++] = MCU_VER_L; + mcuReg[i++] = MCU_VER_H; + mcuReg[i++] = MCU_PRODUCT_INFO; + mcuReg[i++] = START_MODE; + mcuReg[i++] = LUMINANCE_L; + mcuReg[i++] = LUMINANCE_H; + sf_mcu_read_multi(mcuReg, mcuData, i); + i = 0; + McuSubVersion = mcuData[i++]; + + McuVersion = mcuData[i++]; + McuVersion = (UINT16)mcuData[i++] << 8 | McuVersion; + McuProductInfo = mcuData[i++]; + dataTemp1 = mcuData[i++]; + startMode = dataTemp1 & 0x1F; + DailyReportStartMode = (dataTemp1 & 0xc0) >> 6; + dataTemp1= mcuData[i++]; + dataTemp2 = mcuData[i++]; + IRSHTTER = (dataTemp2 << 8) | dataTemp1; + } + + McuPowerOnMode = startMode; + return startMode; +} + +unsigned char sf_mcu_rtc_get (SF_TIME_S *time) +{ + UINT8 mcuReg[REG_SIZE] = { 0 }; + UINT8 mcuData[REG_SIZE] = { 0 }; + UINT8 i = 0; + mcuReg[i++] = SF_RTC_YEAR; + mcuReg[i++] = SF_RTC_MONTH; + mcuReg[i++] = SF_RTC_DAY; + mcuReg[i++] = SF_RTC_HOUR; + mcuReg[i++] = SF_RTC_MINUTE; + mcuReg[i++] = SF_RTC_SEC; + + sf_mcu_read_multi(mcuReg, mcuData, i); + i = 0; + time->Year = mcuData[i++] + 2000; + time->Mon= mcuData[i++]; + time->Day = mcuData[i++]; + time->Hour= mcuData[i++]; + time->Min = mcuData[i++]; + time->Sec= mcuData[i++]; + + printf("date:%d-%d-%d %d:%d:%d\n", time->Year, time->Mon, time->Day, time->Hour, time->Min, time->Sec); + return 0; +} +unsigned char sf_mcu_wdg_off(void) +{ + unsigned char i = 0; + unsigned char regsize =0; + unsigned char mcuReg[2] = {0}; + unsigned char mcuPara[2] = {0}; + + mcuReg[i] = FUNCTION_SWTICH2; + mcuPara[i++] = 1; + + mcuReg[i] = DSP_WRITE_FLG; + mcuPara[i++] = 1; + + regsize = i; + + for(i=0; i reg:18/9/7*/ + +#else /*analog PIR*/ +const unsigned char PirDigtSensLevel[3] = {0, 1, 2}; // /*analog PIR: High/Middle/Low/OFF*/ +#endif + +#define APP_POWER_OFF_APO 0 +#define APP_POWER_OFF_BATT_EMPTY 0 +extern SF_TIME_S sf_get_mcu_poweroff_date(void); +UINT8 sf_set_digit_pir_level(UINT8 pirs) +{ + UINT8 digPirLevel[10] = {200, 38, 30, 24, 18, 16, 10, 9, 8, 7}; + + if(pirs > 9) + pirs = 9; + + return digPirLevel[pirs]; +} + +UINT8 sf_set_digit_pir_pulse_cnt(UINT8 pirs) +{ + UINT8 digPirPulseCnt[10] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1};; + + if(pirs > 9) + pirs = 9; + + return digPirPulseCnt[pirs]; +} + +unsigned char sf_mcu_reg_set(MCUParam_t attrId, unsigned char val) +{ + unsigned char mcuReg[70] = {0}; + unsigned char mcuData[70] = {0}; + unsigned char regsize =0; + unsigned char i = 0; + unsigned char temp = 0; + //unsigned char dailyReportFlag = 1; + unsigned char paraSyncFlag = 0; + //unsigned char gpsAlwaysFlag = 0; + unsigned char DigPirPulseCount = 0; + unsigned char DigPirWindowTime = 0; + SF_PDT_PARAM_CFG_S *puiPara = sf_customer_param_get(); + SF_PARA_TIME_S date = { 0 }; + //CameraBootSetting_t* pCameraBootSetting = CameraBootSettingGetHandle(); + + if (attrId > SF_MCU_PARAM_MAX) + { + MLOGE("attrId ERROR!\n"); + return -1; + } + + + if(attrId == SF_MCU_POWEROFF) + { + //printf("SynMcuSet = %x\n", statisPara->SynMcuSet); + MLOGI("GPSEnterResetModeFlag = %d\n", puiPara->GPSEnterResetModeFlag); + if(puiPara->GPSEnterResetModeFlag == 1) + { + paraSyncFlag = 1; + } + + + sf_sys_rtc_time_get(&date); + MLOGI("%04d/%02d/%02d %02d:%02d:%02d\n", + date.Year, date.Mon, date.Day, date.Hour, date.Min, date.Sec); + mcuReg[i] = SF_RTC_YEAR; + mcuData[i++] = date.Year-2000; + mcuReg[i] = SF_RTC_MONTH; + mcuData[i++] = date.Mon; + mcuReg[i] = SF_RTC_DAY; + mcuData[i++] = date.Day; + mcuReg[i] = SF_RTC_HOUR; + mcuData[i++] = date.Hour; + mcuReg[i] = SF_RTC_MINUTE; + mcuData[i++] = date.Min; + mcuReg[i] = SF_RTC_SEC; + mcuData[i++] = date.Sec; + + + if(puiPara->PirSwitch) + temp = 0x01; + else + temp = 0x00; + + if(puiPara->GprsMode == 0) + temp |= 0x20; + + if(puiPara->TimelapseSwitch) + temp |= 0x02; + + + if(puiPara->PirDelaySwitch) + temp |= 0x04; + if(paraSyncFlag ) + temp |= 0x08; + + temp |= 0x10; + + mcuReg[i] = FUNCTION_SWTICH0; + mcuData[i++] = temp; + + temp = 0; + + + if(paraSyncFlag) + { + mcuReg[i] = GPS_POWER_TIMER_CLEAR; + mcuData[i++] = 1; + mcuReg[i] = GPS_POWER_CTRL; + mcuData[i++] = 1; + } + else + { + mcuReg[i] = GPS_POWER_CTRL; + mcuData[i++] = 0; + } + + MLOGI("PirSensitivity=%d\n", puiPara->PirSensitivity); + mcuReg[i] = ANALOG_PIR_SENSITIVITY; + temp = puiPara->PirSensitivity; + + +// if(paraSyncFlag) { +// temp |= 0x10; +// } + + MLOGI("GprsMode:%d\n",puiPara->GprsMode); +// #ifdef SF_HARDWARE_TEST +// temp |= 0x40; //bit 6-bit5: 2 instant, 1 hybird, 0: daily +// #else + + if((puiPara->GprsMode < 10)) + { + if((puiPara->GprsMode == 1)) + temp |= 0x40; //bit 6-bit5: 2 instant, 1 hybird, 0: daily + else + temp |= 0x20; //bit 6-bit5: 2 instant, 1 hybird, 0: daily + } +// #endif + if((puiPara->GprsSwitch)) + temp |= 0x80; + if((val == SF_POWEROFF_SYNC_PARAM)) + temp &= 0x9F; + + mcuData[i++] = temp; + +#if 1 //DIGITAL_PIR + MLOGI("DigitPirSensitivity=%d\n", puiPara->DigitPirSensitivity); + DigPirPulseCount = sf_set_digit_pir_pulse_cnt(puiPara->DigitPirSensitivity); + DigPirWindowTime = 0; + + mcuReg[i] = DIGITAL_PIR_SENSITIVITY; + + mcuData[i++] = sf_set_digit_pir_level(puiPara->DigitPirSensitivity); + mcuReg[i] = DIGITAL_PIR_CFG; + mcuData[i++] = DigPirWindowTime<<4 | DigPirPulseCount; + +#endif + + + //DSP busy/idle + + mcuReg[i] = DSP_BUSY_STATUS; + mcuData[i++] = 0; + + temp = 1; + if(val == SF_POWEROFF_SD_FULL || SF_SD_FULL == sf_sd_status_get()) + temp |= 0x02; + if(val == SF_POWEROFF_NO_SD) + temp &= ~0x01; + + mcuReg[i] = SYS_STATUS; + mcuData[i++] = temp; + + + temp = 0; + if((val == SF_POWEROFF_KEYON) || (val == SF_POWEROFF_SYNC_PARAM)) + temp |= 0x01; //bit0-3:1, reboot in A + else if(val == SF_POWEROFF_AUTO) + temp |= 0x81; // bit7:1 auto power when 3min no operation + else if(val == SF_POWEROFF_LOW_BAT) + temp |= 0x40; + + mcuReg[i] = POWEROFF_TYPE; + mcuData[i++] = temp; + + //battery recovery + mcuReg[i] = VBAT_RECOVER_VAL; + mcuData[i++] = 72; //SF_BATT_RECOVERY; + + + if(puiPara->TimelapseSwitch) + { + mcuReg[i] = TIMELAPSE_HOUR; + mcuData[i++] = puiPara->TimelapseTime.Hour; + mcuReg[i] = TIMELAPSE_MINUTE; + mcuData[i++] = puiPara->TimelapseTime.Min; + mcuReg[i] = TIMELAPSE_SEC; + + if((puiPara->TimelapseSwitch)&&(puiPara->TimelapseTime.Hour==0)&&(puiPara->TimelapseTime.Min==0)&&(puiPara->TimelapseTime.Sec==0)) + mcuData[i++] = 5; + else + mcuData[i++] = puiPara->TimelapseTime.Sec; + } + else + { + mcuReg[i] = TIMELAPSE_HOUR; + mcuData[i++] = 0; + mcuReg[i] = TIMELAPSE_MINUTE; + mcuData[i++] = 0; + mcuReg[i] = TIMELAPSE_SEC; + mcuData[i++] = 0; + } + + if(puiPara->PirDelaySwitch) + { + mcuReg[i] = PIR_DELAY_HOUR; + mcuData[i++] = puiPara->PirDelayTime.Hour; + mcuReg[i] = PIR_DELAY_MINUTE; + mcuData[i++] = puiPara->PirDelayTime.Min; + mcuReg[i] = PIR_DELAY_SEC; + mcuData[i++] = puiPara->PirDelayTime.Sec; + } + else + { + mcuReg[i] = PIR_DELAY_HOUR; + mcuData[i++] = 0; + mcuReg[i] = PIR_DELAY_MINUTE; + mcuData[i++] = 0; + mcuReg[i] = PIR_DELAY_SEC; + mcuData[i++] = 0; + } + + if(paraSyncFlag) + { + mcuReg[i] = TIME_SYNC_HOUR; + mcuData[i++] = 0; + mcuReg[i] = TIME_SYNC_MINUTE; + mcuData[i++] = 1; + mcuReg[i] = TIME_SYNC_SEC; + mcuData[i++] = 30; + + } + MLOGI("GPSWaitRestartFlag = %d\n", puiPara->GPSWaitRestartFlag); + + if(puiPara->GprsMode == 1) + { + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + 2) % 24; + mcuReg[i] = DAILY_REPORT_MINUTE; + mcuData[i++] = date.Min; + } + else + { +// if(puiPara->DailyReportTime.Min == 30) +// { +// puiPara->DailyReportTime.Min = 2; +// } + if(puiPara->GPSWaitRestartFlag == 2) + { puiPara->DailyReportTime.Hour = 0; + puiPara->DailyReportTime.Min = 1; + } + + if(puiPara->GprsMode != 2 && puiPara->GPSWaitRestartFlag == 1) + { + + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + 1) % 24; + mcuReg[i] = DAILY_REPORT_MINUTE; + mcuData[i++] = (date.Min) % 60; + puiPara->GPSWaitRestartFlag = 0; + + } + else + { + puiPara->GPSWaitRestartFlag = 0; + if((date.Min + puiPara->DailyReportTime.Min) > 59) + { + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + puiPara->DailyReportTime.Hour +1) % 24; + } + else + { + mcuReg[i] = DAILY_REPORT_HOUR; + mcuData[i++] = (date.Hour + puiPara->DailyReportTime.Hour) % 24; + } + + mcuReg[i] = DAILY_REPORT_MINUTE; + MLOGI("now time =[%02d:%02d:%02d],DailyReportTimer = [%02d:%02d:00]\n",date.Hour,date.Min,date.Sec, puiPara->DailyReportTime.Hour,puiPara->DailyReportTime.Min); + + + if(puiPara->DailyReportTime.Hour == 24) + mcuData[i++] = (date.Min + puiPara->DailyReportTime.Min - 1) % 60; + else + mcuData[i++] = (date.Min + puiPara->DailyReportTime.Min) % 60; + } + } + + + + + #if 1 //no use + if(puiPara->WorkMode == 1) + { + + mcuReg[i] = DAILY_SEND1_HOUR; + mcuData[i++] = puiPara->TimeSend1.Hour; + mcuReg[i] = DAILY_SEND1_MINUTE; + mcuData[i++] = puiPara->TimeSend1.Min; + + } + +/* + mcuReg[i] = DAILY_SEND2_HOUR; + mcuData[i++] = puiPara->TimeSend2; + mcuReg[i] = DAILY_SEND2_MINUTE; + mcuData[i++] = puiPara->TimeSend2; + + mcuReg[i] = DAILY_SEND3_HOUR; + mcuData[i++] = puiPara->TimeSend3; + mcuReg[i] = DAILY_SEND3_MINUTE; + mcuData[i++] = puiPara->TimeSend3; + + mcuReg[i] = DAILY_SEND4_HOUR; + mcuData[i++] = puiPara->TimeSend4; + mcuReg[i] = DAILY_SEND4_MINUTE; + mcuData[i++] = puiPara->TimeSend4; +*/ + #endif + + + if(puiPara->WorkTime1Switch) + { + mcuReg[i] = WORKTIME1_SWITCH; + + if(puiPara->WorkTime[0].StartTime.Day > 0) + { + mcuData[i++] = puiPara->WorkTime[0].StartTime.Day; + } + else + { + mcuData[i++] = 0xFF; + } + + mcuReg[i] = WORKTIME1_START_HOUR; + mcuData[i++] = puiPara->WorkTime[0].StartTime.Hour; + mcuReg[i] = WORKTIME1_START_MINUTE; + mcuData[i++] = puiPara->WorkTime[0].StartTime.Min; + + mcuReg[i] = WORKTIME1_STOP_HOUR; + mcuData[i++] = puiPara->WorkTime[0].StopTime.Hour; + + mcuReg[i] = WORKTIME1_STOP_MINUTE; + mcuData[i++] = puiPara->WorkTime[0].StopTime.Min; + } + else + { + mcuReg[i] = WORKTIME1_SWITCH; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME1_START_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME1_START_MINUTE; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME1_STOP_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME1_STOP_MINUTE; + mcuData[i++] = 0; + } + + if(puiPara->WorkTime2Switch) + { + mcuReg[i] = WORKTIME2_SWITCH; + if(puiPara->WorkTime[1].StartTime.Day > 0) + { + mcuData[i++] = puiPara->WorkTime[1].StartTime.Day; + } + else + { + mcuData[i++] = 0xFF; + } + + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = puiPara->WorkTime[1].StartTime.Hour; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = puiPara->WorkTime[1].StartTime.Min; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = puiPara->WorkTime[1].StopTime.Hour; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = puiPara->WorkTime[1].StopTime.Min; + } + else + { + mcuReg[i] = WORKTIME2_SWITCH; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = 0; + } + } + + mcuReg[i] = DSP_WRITE_FLG; //MCU set end + mcuData[i++] = 1; + + regsize = i; + + for(i = 0; i < regsize; i++) + { + sf_commu_set_mcu(mcuReg[i], mcuData[i]); + } + return 0; + +} + +SF_TIME_S sf_get_mcu_poweroff_date(void) +{ + return sfMcuTime; +} + +void sf_set_mcu_poweroff_date(SF_PARA_TIME_S date) +{ + sfMcuTime.Year = date.Year - 2000; + sfMcuTime.Mon = date.Mon; + sfMcuTime.Day = date.Day; + sfMcuTime.Hour = date.Hour; + sfMcuTime.Min = date.Min; + sfMcuTime.Sec = date.Sec; +} + + + +//address 85 stJpegAeInfo.unsigned intshutter = stAE_Info.stExpoValueLong.unsigned intUS +//address 86 +//address 87 stJpegAeInfo.SensorGain = stAE_Info.stExpoValueLong.unsigned intSensorGain +//address 88 +//address 89 light val +//address 90 + +int sf_set_ae_shutter(unsigned int value) +{ + signed int ret = -1; + unsigned char val_l = 0; + unsigned char val_h = 0; + val_l = value & 0x000000ff; + val_h = (value & 0x0000ff00) >> 8; + ret = sf_commu_set_mcu(85, val_l); + ret = sf_commu_set_mcu(86, val_h); + return ret; +} + +int sf_set_ae_sensor_gain(unsigned int value) +{ + signed int ret = -1; + unsigned char val_l = 0; + unsigned char val_h = 0; + val_l = value & 0x000000ff; + val_h = (value & 0x0000ff00) >> 8; + ret = sf_commu_set_mcu(87, val_l); + ret = sf_commu_set_mcu(88, val_h); + return ret; +} + + + +int sf_get_ae_shutter(void) +{ + unsigned char val_h = 0; + unsigned char val_l = 0; + unsigned short val = 0; + val_l = sf_commu_get_mcu(85); + val_h = sf_commu_get_mcu(86); + val = val_h; + val = (val << 8) | val_l; + return val; +} + +int sf_get_ae_sensor_gain(void) +{ + unsigned char val_h = 0; + unsigned char val_l = 0; + unsigned short val = 0; + val_l = sf_commu_get_mcu(87); + val_h = sf_commu_get_mcu(88); + val = val_h; + val = (val << 8) | val_l; + return val; +} + + +int sf_set_cur_light_val(unsigned int value) +{ + signed int ret = -1; + unsigned char val_l = 0; + unsigned char val_h = 0; + val_l = value & 0x000000ff; + val_h = (value & 0x0000ff00) >> 8; + ret = sf_commu_set_mcu(89, val_l); + ret = sf_commu_set_mcu(90, val_h); + return ret; +} + + +int sf_get_last_light_val(void) +{ + unsigned char val_l = 0; + unsigned char val_h = 0; + unsigned short val = 0; + val_l = sf_commu_get_mcu(89); + val_h = sf_commu_get_mcu(90); + val = val_h; + val = (val << 8) | val_l; + return val; +} + + +#if 0 +/************************************************* + Function: sf_mcu_version_get + Description: get mcu ver + Input: N/A + Output: ver str + Return: N/A + Others: N/A +*************************************************/ +void sf_mcu_version_get(unsigned char *mcuVer) +{ + unsigned char str[10] = {0}; + + if (McuProductInfo == 1) + { + sprintf(str, "SYAM"); + } + else if(McuProductInfo == 2) + { + sprintf(str, "SYM"); + } + else + { + sprintf(str, "SYPM"); + } + + sprintf(mcuVer, "%s%d.%d.%d", str, (McuVersion>>8)&0xFF, McuVersion & 0xFF, McuSubVersion); +} +#endif + +unsigned char sf_mcu_start_mode_get(void) +{ + return McuPowerOnMode; +} + + + + + + + + + + +SF_BOOL sf_is_night_mode(unsigned int isRefresh) +{ + unsigned char dataTemp1 = 0; + unsigned char dataTemp2 = 0; + unsigned short lightval = 0; + if(isRefresh) + { + dataTemp1 = sf_commu_get_mcu(LUMINANCE_L); + dataTemp2 = sf_commu_get_mcu(LUMINANCE_H); + lightval = (dataTemp2 << 8) | dataTemp1; + IRSHTTER = lightval; + printf("[sf_is_night_mode]IRSHTTER = %d\n", IRSHTTER); + if(lightval < SF_MCU_NIGHT_MODE_LUMINANCE) + { + return SF_TRUE; + }else + { + return SF_FALSE; + } + } + else + { + if(IRSHTTER < SF_MCU_NIGHT_MODE_LUMINANCE) + { + return SF_TRUE; + } + else + { + return SF_FALSE; + } + } +} + +void sf_set_mcu_sub_ver(unsigned char mcuSubVersion) +{ + McuSubVersion = mcuSubVersion; +} + +void sf_set_mcu_ver(unsigned short mcuVersion) +{ + McuVersion = mcuVersion; +} + +unsigned short sf_get_light_value(void) +{ + return IRSHTTER; +} + + +unsigned char sf_get_mcu_sub_ver(void) +{ + return McuSubVersion; +} + +unsigned short sf_get_mcu_ver(void) +{ + return McuVersion; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/code/source/systemMng/sf_systemMng.c b/code/application/source/sf_app/code/source/systemMng/sf_systemMng.c new file mode 100755 index 000000000..5c7199f44 --- /dev/null +++ b/code/application/source/sf_app/code/source/systemMng/sf_systemMng.c @@ -0,0 +1,478 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include "sf_log.h" +#include "sf_ledmng.h" +#include "sf_fileMng.h" +#include "sf_systemMng.h" +#include "sf_commu_mcu_reg.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +static UINT8 PowerOffType = SF_POWEROFF_NOT; +static SF_UPGRADE_STATUS_E UpdateFlag = SF_UPGRADE_BUTT; + +const SF_CHAR* sf_system_poweroff_getstatusstring(SF_POWEROFF_TYPE_E enType) +{ + switch(enType) + { + case SF_POWEROFF_NOT: + return "SF_POWEROFF_NOT"; + case SF_POWEROFF_AUTO: + return "SF_POWEROFF_AUTO"; + case SF_POWEROFF_REBOOT: + return "SF_POWEROFF_REBOOT"; + case SF_POWEROFF_KEYON: + return "SF_POWEROFF_KEYON"; + case SF_POWEROFF_KEYOFF: + return "SF_POWEROFF_KEYOFF"; + case SF_POWEROFF_SYNC_PARAM: + return "SF_POWEROFF_SYNC_PARAM"; + case SF_POWEROFF_GPS_DP: + return "SF_POWEROFF_GPS_DP"; + case SF_POWEROFF_SD_FULL: + return "SF_POWEROFF_SD_FULL"; + case SF_POWEROFF_LOW_BAT: + return "SF_POWEROFF_LOW_BAT"; + case SF_POWEROFF_NO_SD: + return "SF_POWEROFF_NO_SD"; + default: + return "Unknown"; + } +} +SF_UPGRADE_STATUS_E sf_upgrade_status_get(void) +{ + return UpdateFlag; +} + +void sf_upgrade_status_set(SF_UPGRADE_STATUS_E status) +{ + if((status >= SF_UPGRADE_PRE) && (status <= SF_UPGRADE_BUTT)) + { + UpdateFlag = status; + } + MLOGD("UpdateFlag:%d\n", UpdateFlag); +} + + + +SF_POWEROFF_TYPE_E sf_poweroff_type_get(void) +{ + return PowerOffType; +} + +SINT32 sf_poweroff_type_set(SF_POWEROFF_TYPE_E enType) +{ + SF_SYS_CHECK_RANGE(enType,SF_POWEROFF_NOT,SF_POWEROFF_BUTT); + MLOGD("enType = %d \n",enType); + PowerOffType = enType; + + return SF_SUCCESS; +} + +SINT32 sf_sys_rtc_time_get(SF_PARA_TIME_S *pstDateTime) +{ + SF_COMM_CHECK_POINTER(pstDateTime,SF_FAILURE); + time_t t; + struct tm *rtctm; + //SINT32 fdRtc = -1; + int ret = SF_SUCCESS; + time(&t); + rtctm = localtime(&t); + + pstDateTime->Year = rtctm->tm_year + 1900; + pstDateTime->Mon = rtctm->tm_mon + 1; + pstDateTime->Day = rtctm->tm_mday; + pstDateTime->Hour = rtctm->tm_hour; + pstDateTime->Min = rtctm->tm_min; + pstDateTime->Sec = rtctm->tm_sec; + + SLOGI("%d-%d-%d %d:%d:%d\n",pstDateTime->Year,pstDateTime->Mon,pstDateTime->Day,pstDateTime->Hour,pstDateTime->Min,pstDateTime->Sec); + /* + fdRtc = open(DEFAULT_RTC_DEVICE, O_RDWR); + if (fdRtc < 0) + { + MLOGE("open %s error:%s\n", DEFAULT_RTC_DEVICE, strerror(errno)); + return SF_FAILURE; + } + + struct rtc_time rtctm; + if (ioctl(fdRtc, RTC_RD_TIME, &rtctm) < 0) + { + MLOGE("ioctl get rtc time error:%s\n", strerror(errno)); + ret = SF_FAILURE; + } + else + { + pstDateTime->Year = rtctm.tm_year + 1900; + pstDateTime->Mon = rtctm.tm_mon + 1; + pstDateTime->Day = rtctm.tm_mday; + pstDateTime->Hour = rtctm.tm_hour; + pstDateTime->Min = rtctm.tm_min; + pstDateTime->Sec = rtctm.tm_sec; + } + close(fdRtc); + */ + + return ret; +} + +SINT32 sf_sys_rtc_time_set(SF_PARA_TIME_S* pstDateTime) +{ + SF_COMM_CHECK_POINTER(pstDateTime,SF_FAILURE); + + //SINT32 fdRtc = -1; + SINT32 ret = SF_SUCCESS; + + time_t t; + struct tm *tm_info; + struct timeval tv; + + /* 获取当前时间 */ + time(&t); + tm_info = localtime(&t); + + /* 设置时间*/ + tm_info->tm_year = pstDateTime->Year - 1900; /* 年份-1900 后的值 */ + tm_info->tm_mon = pstDateTime->Mon - 1; /* 月份,从0开始计算,9表示10月 */ + tm_info->tm_mday = pstDateTime->Day; /* 日 */ + tm_info->tm_hour = pstDateTime->Hour; /* 时 */ + tm_info->tm_min = pstDateTime->Min; /* 分 */ + tm_info->tm_sec = pstDateTime->Sec; /* 秒 */ + + /* 将struct tm类型的时间转换为struct timeval类型的时间 */ + tv.tv_sec = mktime(tm_info); + tv.tv_usec = 0; + + /* 设置系统时间 */ + if (settimeofday(&tv, NULL) == -1) { + perror("settimeofday error"); + exit(EXIT_FAILURE); + } else { + printf("Time set successfully!\n"); + } + + + /*fdRtc = open(DEFAULT_RTC_DEVICE, O_RDWR); + if (fdRtc < 0) + { + MLOGE("[ERR]open %s error:%d\n", DEFAULT_RTC_DEVICE, fdRtc); + return SF_FAILURE; + } + + struct rtc_time rtctm; + rtctm.tm_year = pstDateTime->Year - 1900; + rtctm.tm_mon = pstDateTime->Mon - 1; + rtctm.tm_mday = pstDateTime->Day; + rtctm.tm_hour = pstDateTime->Hour; + rtctm.tm_min = pstDateTime->Min; + rtctm.tm_sec = pstDateTime->Sec; + + ret=ioctl(fdRtc, RTC_SET_TIME, &rtctm); + if (ret < 0) + { + MLOGE("[ERR]ioctl get rtc time error:%d\n", ret); + } + close(fdRtc); + */ + return ret; +} + +SINT32 sf_sys_rtc_time_check(SF_PARA_TIME_S *pstDateTime) +{ + SF_COMM_CHECK_POINTER(pstDateTime,SF_FALSE); + SLOGI("%d-%d-%d %d:%d:%d\n",pstDateTime->Year,pstDateTime->Mon,pstDateTime->Day,pstDateTime->Hour,pstDateTime->Min,pstDateTime->Sec); + if((pstDateTime->Year >= 2021) && \ + (pstDateTime->Year <= 2050) && \ + (pstDateTime->Mon <= 12) && \ + (pstDateTime->Day <= 31) && \ + (pstDateTime->Hour < 24) && \ + (pstDateTime->Min < 60) && \ + (pstDateTime->Sec < 60)) + { + return SF_TRUE; + } + + return SF_FALSE; +} +SINT32 sf_sys_rtc_time_reset(void) +{ + SINT32 fdRtc = -1; + SINT32 ret = SF_SUCCESS; + fdRtc = open(DEFAULT_RTC_DEVICE, O_RDWR); + + if (fdRtc < 0) + { + MLOGE("open [%s] error:[%d]\n", DEFAULT_RTC_DEVICE, fdRtc); + return SF_FAILURE; + } + + struct rtc_time rtctm; + rtctm.tm_year = 2022 - 1900; + rtctm.tm_mon = 0; + rtctm.tm_mday = 1; + rtctm.tm_hour = 8; + rtctm.tm_min = 0; + rtctm.tm_sec = 0; + + ret=ioctl(fdRtc,RTC_SET_TIME, &rtctm); + if (ret < 0) + { + MLOGE("[ERR]ioctl get rtc time error:%d\n", ret); + } + close(fdRtc); + + return ret; +} + +SINT64 sf_sys_os_time_get(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + +SINT64 sf_sys_os_utime_get(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec; +} + +SINT32 sf_sys_software_version_get(SF_CHAR* version) +{ + #ifdef SF_VERSION_RELEASE + snprintf((char *)version, SF_VER_MAX_LEN, "%s", "T2R3HKrD101"); + #else + snprintf((char *)version, SF_VER_MAX_LEN, "%s", "4SD1HKrCC06");//4SA1HKrCA0A + #endif + + return SF_SUCCESS; +} +SINT32 sf_sys_camera_about(void) +{ + SF_CHAR Temp[128] = {0}; + SF_PDT_PARAM_STATISTICS_S *pstaticparam = sf_statistics_param_get(); + FILE *fp; + if((fp =fopen(SF_VER_FILE_PATH,"w+")) == NULL) + { + MLOGE("open [%s] failed!!!\n",SF_VER_FILE_PATH); + return SF_FAILURE; + } + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + fseek(fp, 0L, SEEK_END); + sprintf(Temp,"IMEI:%s\r\n",pstaticparam->IMEI); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + + SF_CHAR version[12] = {0}; + sf_sys_software_version_get(version); + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + + sprintf(Temp,"SoftwareVER:%s\r\n",version); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + sprintf(Temp,"ModuleVER:%s\r\n",pstaticparam->ModuleVersion); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + sprintf(Temp, "McuVER:%d.%d.%d\r\n", (sf_get_mcu_ver() & 0xff00) >> 8, sf_get_mcu_ver() & 0x00ff, sf_get_mcu_sub_ver()); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + sprintf(Temp,"ICCID:%s\r\n",pstaticparam->SimID); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + sprintf(Temp,"Account:%s\r\n",pstaticparam->BindAccount); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + + memset(Temp,'\0',sizeof(Temp)/sizeof(char)); + sprintf(Temp,"AccessKey:%s\r\n",ACCESS_KEY); + fwrite(Temp,sizeof(char), strlen(Temp),fp); + fflush(fp); + fclose(fp); + + return SUCCESS; +} + +SINT32 sf_sys_rtoscmd_set(SINT8 cmd, SINT8 *para) +{ +// SF_COMM_CHECK_POINTER(para,SF_FAILURE); + SF_SYS_CHECK_RANGE(cmd,LINUX2RTK_CMD_STOP_RECORD,LINUX2RTK_CMD_SET_BUTT); + + SF_RTOS_CMD_T rtos_cmd; + SINT32 nMsysFd = -1; + SINT32 ret= -1; + SF_PARA_TIME_S date; + SF_PDT_PARAM_CFG_S *pCustomerParam = sf_customer_param_get(); + + memset(&rtos_cmd,0x0,sizeof(SF_RTOS_CMD_T)); + rtos_cmd.cmd = cmd; + switch(cmd) + { + case LINUX2RTK_CMD_STOP_RECORD: + break; + case LINUX2RTK_CMD_SET_RTKMODE: + if(para) + { + rtos_cmd.arg[0] = *para; + rtos_cmd.arg[1] = 1; + rtos_cmd.arg[2] = 1; + + if(pCustomerParam->VideoSize ==SF_VIDEO_SIZE_720) + pCustomerParam->VideoLenth = 20; + else if(pCustomerParam->VideoSize ==SF_VIDEO_SIZE_WVGA) + pCustomerParam->VideoLenth = 30; + else + pCustomerParam->VideoLenth = 10; + + rtos_cmd.arg[3] = pCustomerParam->VideoLenth; + rtos_cmd.arg[4] = pCustomerParam->ImgSize; + rtos_cmd.arg[5] = pCustomerParam->VideoSize; + + + } + break; + case LINUX2RTK_CMD_SET_POWEROFF: + rtos_cmd.arg[0] = para[0]; + break; + case LINUX2RTK_CMD_SET_RTCTIME: + + ret = sf_sys_rtc_time_get(&date); + if(SF_TRUE != sf_sys_rtc_time_check(&date)) + { + ret = sf_sys_rtc_time_reset(); + date.Year = 2022; + date.Mon = 1; + date.Day = 1; + date.Hour = 8; + date.Min = 0; + date.Sec = 0; + } + + rtos_cmd.arg[0] = date.Year - 2000; + rtos_cmd.arg[1] = date.Mon; + rtos_cmd.arg[2] = date.Day; + rtos_cmd.arg[3] = date.Hour; + rtos_cmd.arg[4] = date.Min; + rtos_cmd.arg[5] = date.Sec; + SLOGI("%d-%d-%d %d:%d:%d\n",date.Year,date.Mon,date.Day,date.Hour,date.Min,date.Sec); + break; + case LINUX2RTK_CMD_SET_DEVINFO: + + break; + case LINUX2RTK_CMD_SET_P2PCTRL: + if(para) + { + rtos_cmd.arg[0] = 9; + rtos_cmd.arg[1] = *para; + } + break; + case LINUX2RTK_CMD_SET_OTHER: + if(para) + { + rtos_cmd.arg[0] = *para; + rtos_cmd.arg[1] = *(para + 1); + rtos_cmd.arg[2] = *(para + 2); + } + break; + default: + MLOGE("parameter [%d] undefined!!!\n",cmd); + break; + } + + for(SINT32 cnt = 0; cnt < 10 ; cnt++) + { + if(0 > (nMsysFd = open("/dev/msys", O_RDONLY | O_SYNC))) + { + printf( "%s open /dev/msys failed!!\n", __FUNCTION__); + usleep(20000); + continue; + } + else + { + ret = ioctl(nMsysFd, IOCTL_MSYS_SET_RTOS_CMD, &rtos_cmd); + close(nMsysFd); + return ret; + } + } + return ret; +} + +SINT32 sf_sys_rtosdata_get(SF_RTOSINFO_S *pstRtosData) +{ + SF_COMM_CHECK_POINTER(pstRtosData,SF_FAILURE); + + SINT32 nMsysFd = SF_FAILURE; + memset(pstRtosData, 0x00, sizeof(SF_RTOSINFO_S)); + for(SINT32 cnt = 0; cnt < 100 ; cnt++) + { + if(0 > (nMsysFd = open("/dev/msys", O_RDONLY | O_SYNC))) + { + MLOGE( "open /dev/msys failed!!\n"); + usleep(20000); + continue; + } + else + { + + ioctl(nMsysFd, IOCTL_MSYS_GET_SY_RTOS_DATA, pstRtosData); + close(nMsysFd); + break; + } + } + + return nMsysFd; +} + +SINT32 sf_sys_poweroff(SF_POWEROFF_TYPE_E poweroffType) +{ + SF_SYS_CHECK_RANGE(poweroffType ,SF_POWEROFF_NOT,SF_POWEROFF_BUTT); + SLOGI("poweroffType = [%d,%s]\n",poweroffType,sf_system_poweroff_getstatusstring(poweroffType)); + SINT32 ret = SF_FAILURE; + + system("umount misc"); + system("echo cli sycmd -wpara > /proc/dualos/rtos"); + usleep(100*1000); + + ret = sf_sys_rtoscmd_set(LINUX2RTK_CMD_SET_RTCTIME, NULL); + usleep(100*1000); + + /*ret = sf_sys_rtoscmd_set(LINUX2RTK_CMD_SET_POWEROFF, setRtosPara); + usleep(100*1000);*/ + + ret = sf_mcu_reg_set(SF_MCU_POWEROFF, poweroffType); + + return ret; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/ttyusb/sf_hal_ttyusb.c b/code/application/source/sf_app/code/source/ttyusb/sf_hal_ttyusb.c new file mode 100755 index 000000000..91fa57d6c --- /dev/null +++ b/code/application/source/sf_app/code/source/ttyusb/sf_hal_ttyusb.c @@ -0,0 +1,415 @@ +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: jiamin + * + * Ver: 1.0.0 2020/9/10 + * +**************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "sf_type.h" +#include "sf_log.h" +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +static SINT32 TtyUSB2Fd = -1; +static SINT32 UartFd = -1; +static SINT32 hal_ttyusb_open(SF_CHAR* deviceName) +{ + SINT16 ret = -1; + SINT32 fd = -1; + fd = open(deviceName, O_RDWR|O_NOCTTY|O_NONBLOCK); + if (-1 == fd) + { + return SF_FAILURE; + } + + ret = fcntl(fd, F_SETFL, 0); + if(ret < 0) + { + MLOGE("fcntl failed!\n"); + return SF_FAILURE; + } + + return fd; +} +static SINT32 hal_ttyusb_config(SINT32 fd, SF_SERIAL_DATA_FRAME_TYPE_S *pSerialAttr) +{ + + SINT32 i; + SINT32 speed_arr[] = {B115200, B460800}; + SINT32 name_arr[] = {115200, 460800}; + struct termios options; + + if(tcgetattr( fd,&options) != 0) + { + printf("SetupSerial 1"); + return SF_FAILURE; + } + + //cfmakeraw(&options); + + for (i= 0; i < sizeof(speed_arr) / sizeof(int); i++) + { + if(pSerialAttr->speed == name_arr[i]) + { + cfsetispeed(&options, speed_arr[i]); + cfsetospeed(&options, speed_arr[i]); + } + } +#if 1 + //options.c_cflag |= CLOCAL; + //options.c_cflag |= CREAD; + + switch(pSerialAttr->flow_ctrl) + { + case 'n': + case 'N'://不使用流控制 + options.c_cflag &= ~(600);//CRTSCTS; + break; + + case 'h': + case 'H'://使用硬件流控制 + options.c_cflag |= 600;//CRTSCTS; + break; + + case 'S': + case 's'://使用软件流控制 + options.c_cflag |= IXON | IXOFF | IXANY; + break; + } + + //设置数据位 + options.c_cflag &= ~CSIZE; //屏蔽其他标志位 + + switch (pSerialAttr->databits) + { + case 5: + options.c_cflag |= CS5; + break; + + case 6: + options.c_cflag |= CS6; + break; + + case 7: + options.c_cflag |= CS7; + break; + + case 8: + options.c_cflag |= CS8; + break; + + default: + fprintf(stderr,"Unsupported data size/n"); + return SF_FAILURE; + } + + //设置校验位 + switch (pSerialAttr->parity) + { + case 'n': + case 'N': //无奇偶校验位 + options.c_cflag &= ~PARENB; + options.c_iflag &= ~INPCK; + break; + + case 'o': + case 'O'://设置为奇校验 + options.c_cflag |= (PARODD | PARENB); + options.c_iflag |= INPCK; + break; + + case 'e': + case 'E'://设置为偶校验 + options.c_cflag |= PARENB; + options.c_cflag &= ~PARODD; + options.c_iflag |= INPCK; + break; + + case 's': + case 'S': //设置为空格 + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + break; + + default: + fprintf(stderr,"Unsupported parity/n"); + return SF_FAILURE; + } + + // 设置停止位 + switch (pSerialAttr->stopbits) + { + case 1: + options.c_cflag &= ~CSTOPB; + break; + + case 2: + options.c_cflag |= CSTOPB; + break; + + default: + fprintf(stderr,"Unsupported stop bits/n"); + return SF_FAILURE; + } + + //修改输出模式,原始数据输出 + options.c_oflag &= ~OPOST; + + //激活配置 (将修改后的termios数据设置到串口中) + if (tcsetattr(fd,TCSANOW,&options) != 0) + { + printf("com set error!/n"); + return SF_FAILURE; + } + + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG ); + options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + + //设置等待时间和最小接收字符 + options.c_cc[VTIME] = 0; + options.c_cc[VMIN] = 1; + + //如果发生数据溢出,接收数据,但是不再读取 + tcflush(fd,TCIFLUSH); +#endif + + //激活配置 (将修改后的termios数据设置到串口中) + if (tcsetattr(fd,TCSANOW,&options) != 0) + { + printf("com set error!/n"); + return SF_FAILURE; + } + + return SF_SUCCESS; +} + +static SINT32 hal_ttyusb_write(SINT32 fd, SF_CHAR *sendBuf, SINT32 dataLen) +{ + SINT32 len = 0; + + len = write(fd,sendBuf,dataLen); + if (len == dataLen ) + { + return SF_SUCCESS; + } + else + { + tcflush(fd,TCOFLUSH); + MLOGE("write fail!\n"); + return SF_FAILURE; + } +} +#if 0 +static SINT32 hal_ttyusb_read(SINT32 fd, SF_CHAR *recvBuf, SINT32 waitTime) +{ + //SF_PDT_PARAM_CFG_S *sfParam = sf_customer_param_get(); + SINT32 retv = 0; + + if(waitTime > 0) + sf_sleep_ms(waitTime); + + retv = read(fd, recvBuf, SF_TTYUSB_RECV_MAX); /*read data*/ + if(retv == -1) + { + MLOGE("read bad1"); /*check read is ok*/ + return SF_FAILURE; + } + + + return SF_SUCCESS; +} +#else + +static SINT32 hal_ttyusb_read(SINT32 fd, SF_CHAR *recvBuf, SINT32 waitTime) +{ + //SF_PDT_PARAM_CFG_S *sfParam = sf_customer_param_get(); + SINT32 s32ret = 0; + fd_set read_fds; + struct timeval TimeoutVal; + if(waitTime > 0) + sf_sleep_ms(waitTime); + + while(waitTime--){ + + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + TimeoutVal.tv_sec = 0; + TimeoutVal.tv_usec = 10000; + + s32ret = select(fd + 1, &read_fds, NULL, NULL, &TimeoutVal); + if (s32ret > 0) { + if (FD_ISSET(fd, &read_fds)) { + s32ret = read(fd, recvBuf, 580); + if (s32ret > 0) { + break; + } + } + FD_CLR(fd, &read_fds); + } + else if (s32ret < 0) { + //MLOGE(" select failed\n"); + continue; + } + else if (0 == s32ret) { + //MLOGW("FIFO select timeout [%d]\n",waitTime); + continue; + } + + } + + return SF_SUCCESS; +} +#endif + + +static SINT32 hal_ttyusb_create(SF_CHAR *ttyusbName,SF_SERIAL_DATA_FRAME_TYPE_S *pSerialAttr,SINT32 *pttyfd) +{ + + SINT32 ret = SF_FAILURE; + SINT8 i = 0; + while(i < 2) + { + if(SF_FAILURE < (*pttyfd = hal_ttyusb_open(ttyusbName))) + break; + i++; + usleep(100000); + } + + if(*pttyfd <= 0) + return SF_FAILURE; + + ret = hal_ttyusb_config(*pttyfd,pSerialAttr); + if(SF_FAILURE == ret) + { + MLOGE("config [%s] Fail!\n",ttyusbName); + return SF_FAILURE; + } + + return ret; +} +static SINT32 hal_ttyusb_destory(SINT32 fd) +{ + int ret = 0; + int count = 0; + + while ((ret = close(fd)) < 0) + { + usleep(100000); + + count++; + if(count > 10) + { + MLOGE("Close USB File Failed.\n"); + break; + } + } + return ret; +} +SINT32 sf_hal_ttyusb2_init(void) +{ + SINT32 ret = SF_FAILURE; + if(TtyUSB2Fd > 0) + { + MLOGE("[/dev/ttyUSB2] has already inited !!!\n"); + return SF_FAILURE; + } + + SF_SERIAL_DATA_FRAME_TYPE_S stserialtype = {0}; + stserialtype.parity = 'N'; + stserialtype.flow_ctrl = 'N'; + + stserialtype.speed = 460800; + stserialtype.databits = 8; + stserialtype.stopbits = 1; + ret = hal_ttyusb_create("/dev/ttyUSB2",&stserialtype,&TtyUSB2Fd); + + return ret; + + +} +SINT32 sf_hal_ttyusb2_write(SF_CHAR *sendBuf, SINT32 dataLen) +{ + return hal_ttyusb_write(TtyUSB2Fd,sendBuf,dataLen); +} +SINT32 sf_hal_ttyusb2_read(SF_CHAR *recvBuf, SINT32 dataLen) +{ + return hal_ttyusb_read(TtyUSB2Fd,recvBuf,dataLen); +} +SINT32 sf_hal_ttyusb2_deinit(void) +{ + if(TtyUSB2Fd < 0) + { + MLOGE("[/dev/ttyUSB2] has already deinited !!!\n"); + return SF_FAILURE; + } + + return hal_ttyusb_destory(TtyUSB2Fd); +} +SINT32 sf_hal_uart_init(void) +{ + SINT32 ret = SF_FAILURE; + if(UartFd > 0) + { + MLOGE("[/dev/ttyS2] has already inited !!!\n"); + return SF_FAILURE; + } + + SF_SERIAL_DATA_FRAME_TYPE_S stserialtype = {0}; + stserialtype.parity = 'N'; + stserialtype.flow_ctrl = 'N'; + + stserialtype.speed = 115200; + stserialtype.databits = 8; + stserialtype.stopbits = 1; + ret = hal_ttyusb_create("/dev/ttyS2",&stserialtype,&UartFd); + + return ret; +} +SINT32 sf_hal_uart_write(SF_CHAR *sendBuf, SINT32 dataLen) +{ + return hal_ttyusb_write(UartFd,sendBuf,dataLen); +} +SINT32 sf_hal_uart_read(SF_CHAR *recvBuf, SINT32 dataLen) +{ + return hal_ttyusb_read(UartFd,recvBuf,dataLen); +} +SINT32 sf_hal_uart_deinit(void) +{ + if(UartFd < 0) + { + MLOGE("[/dev/ttyUSB2] has already deinited !!!\n"); + return SF_FAILURE; + } + + return hal_ttyusb_destory(UartFd); +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/code/application/source/sf_app/code/source/utils/mbedtls.c b/code/application/source/sf_app/code/source/utils/mbedtls.c new file mode 100755 index 000000000..4105e305b --- /dev/null +++ b/code/application/source/sf_app/code/source/utils/mbedtls.c @@ -0,0 +1,66851 @@ +/* + * MbedTLS Source Code Library Source + */ + +#include "mbedtls.h" + + +#if 1//ME_COM_MBEDTLS + + +/********* Start of file library/aes.c ************/ + +/* + * FIPS-197 compliant AES implementation + * + * 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) + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_AES_C) + +#include + + +#if defined(MBEDTLS_PADLOCK_C) + +#endif +#if defined(MBEDTLS_AESNI_C) + +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + while( length-- ) + { + memcpy( ov, iv, 16 ); + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 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 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 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, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 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, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + int len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_tests = aes_test_cfb128_pt; + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ctr_ct[u], len ); + aes_tests = aes_test_ctr_pt[u]; + } + else + { + memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/aesni.c ************/ + +/* + * AES-NI support functions + * + * 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) + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_AESNI_C) + + + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/arc4.c ************/ + +/* + * An implementation of the ARCFOUR algorithm + * + * 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) + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ARC4_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARC4_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); +} + +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int mbedtls_arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + mbedtls_arc4_context ctx; + + mbedtls_arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); + mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_arc4_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARC4_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/asn1parse.c ************/ + +/* + * Generic ASN.1 parsing + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + + + +#include + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_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( MBEDTLS_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( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + mbedtls_asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if( *p < end ) + { + cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, + sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/asn1write.c ************/ + +/* + * ASN.1 buffer writing functionality + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ASN1_WRITE_C) + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = 0x83; + return( 4 ); + } + + if( len <= 0xFFFFFFFF ) + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = ( len >> 24 ) & 0xFF; + *--(*p) = 0x84; + return( 5 ); + } + + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +} + +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) +{ + int ret; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + int ret; + size_t len = 0; + + // TODO negative values and values larger than 128 + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len += 1; + *--(*p) = val; + + if( val > 0 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0, size; + + size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + + // Calculate byte length + // + if( *p < start || (size_t)( *p - start ) < size + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = (unsigned char) (size * 8 - bits); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/base64.c ************/ + +/* + * RFC 1521 base64 encoding/decoding + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_BASE64_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( ( i + 1 ) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = j = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + x = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( x != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= j; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/bignum.c ************/ + +/* + * Multi-precision integer library + * + * 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) + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_BIGNUM_C) + + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { + volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; +} + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +{ + int ret; + mbedtls_mpi_uint r; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + + if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + /* + * Round up the buffer length to an even value to ensure that there is + * enough room for hexadecimal values that can be represented in an odd + * number of digits. + */ + n += 3 + ( ( n + 1 ) & 1 ); + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > 0; i--, j++ ) + X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mbedtls_mpi_size( X ); + + if( buflen < n ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mbedtls_mpi subtraction + */ +static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret; + size_t n; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + mbedtls_mpi_init( &TB ); + + if( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi TA, TB; + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i++; j > 0; j-- ) + mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + if( T->n < N->n + 1 || T->p == NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); + + return( 0 ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + return( mpi_montmul( A, &U, N, mm, T ) ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t lz, lzt; + mbedtls_mpi TG, TA, TB; + + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( size > MBEDTLS_MPI_MAX_SIZE ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, n, s; + mbedtls_mpi W, R, T, A, RR; + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + i = mbedtls_mpi_bitlen( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi XX; + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); +} + +/* + * Prime number generation + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t k, n; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mbedtls_mpi_bitlen( X ); + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); + + mbedtls_mpi_set_bit( X, nbits-1, 1 ); + + X->p[0] |= 1; + + if( dh_flag == 0 ) + { + while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); + } + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + { + break; + } + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/blowfish.c ************/ + +/* + * Blowfish implementation + * + * 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) + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + + + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); +} + +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + ( keybits % 8 ) ) + { + return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + } + + keybits >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keybits ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* MBEDTLS_BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + + if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) + return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); + mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !MBEDTLS_BLOWFISH_ALT */ +#endif /* MBEDTLS_BLOWFISH_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/camellia.c ************/ + +/* + * Camellia implementation + * + * 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) + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX4((I0 ) & 0xFF) ); + I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX1((I1 ) & 0xFF) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); + GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + GET_UINT32_BE( KC[i], t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + GET_UINT32_BE( X[0], input, 0 ); + GET_UINT32_BE( X[1], input, 4 ); + GET_UINT32_BE( X[2], input, 8 ); + GET_UINT32_BE( X[3], input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + PUT_UINT32_BE( X[2], output, 0 ); + PUT_UINT32_BE( X[3], output, 4 ); + PUT_UINT32_BE( X[0], output, 8 ); + PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 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 } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 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, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 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, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + mbedtls_camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ccm.c ************/ + +/* + * NIST SP800-38C compliant CCM implementation + * + * 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) + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CCM_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_CCM_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +/* + * Initialize context + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); +} + +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \ + return( ret ); \ + \ + for( i = 0; i < len; i++ ) \ + dst[i] = src[i] ^ b[i]; + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char i; + unsigned char q; + size_t len_left, olen; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + */ + if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( add_len > 0xFF00 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + q = 16 - 1 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= ( add_len > 0 ) << 6; + b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; + b[0] |= q - 1; + + memcpy( b + 1, iv, iv_len ); + + for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) + b[15-i] = (unsigned char)( len_left & 0xFF ); + + if( len_left > 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + + /* Start CBC-MAC with first block */ + memset( y, 0, 16 ); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if( add_len > 0 ) + { + size_t use_len; + len_left = add_len; + src = add; + + memset( b, 0, 16 ); + b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); + b[1] = (unsigned char)( ( add_len ) & 0xFF ); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy( b + 2, src, use_len ); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while( len_left > 0 ) + { + use_len = len_left > 16 ? 16 : len_left; + + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy( ctr + 1, iv, iv_len ); + memset( ctr + 1 + iv_len, 0, q ); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while( len_left > 0 ) + { + size_t use_len = len_left > 16 ? 16 : len_left; + + if( mode == CCM_ENCRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + } + + CTR_CRYPT( dst, src, use_len ); + + if( mode == CCM_DECRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, dst, use_len ); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for( i = 0; i < q; i++ ) + if( ++ctr[15-i] != 0 ) + break; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < q; i++ ) + ctr[15-i] = 0; + + CTR_CRYPT( y, y, 16 ); + memcpy( tag, y, tag_len ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_zeroize( output, length ); + return( MBEDTLS_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* !MBEDTLS_CCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 + +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res[NB_TESTS][32] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 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 } +}; + +int mbedtls_ccm_self_test( int verbose ) +{ + mbedtls_ccm_context ctx; + unsigned char out[32]; + size_t i; + int ret; + + mbedtls_ccm_init( &ctx ); + + if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + msg, out, + out + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + res[i], out, + res[i] + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( out, msg, msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_ccm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CCM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/certs.c ************/ + +/* + * X.509 test certificates + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#if defined(MBEDTLS_CERTS_C) + +#if defined(MBEDTLS_ECDSA_C) +#define TEST_CA_CRT_EC \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ +"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ +"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ +"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ +"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ +"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ +"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ +"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ +"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; +const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); + +const char mbedtls_test_ca_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" +"\r\n" +"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" +"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" +"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" +"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); + +const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; + +const char mbedtls_test_srv_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" +"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" +"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" +"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" +"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" +"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" +"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" +"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" +"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); + +const char mbedtls_test_srv_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" +"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" +"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); + +const char mbedtls_test_cli_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" +"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" +"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" +"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" +"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" +"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" +"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" +"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); + +const char mbedtls_test_cli_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" +"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" +"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_RSA_C) + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA_SHA256 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTcwNTA0MTY1NzAxWhcNMjcwNTA1MTY1NzAxWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/MGMGA1UdIwRcMFqA\r\n" \ +"FLRa5KWz3tJS9rnVppUP6z68x/3/oT+kPTA7MQswCQYDVQQGEwJOTDERMA8GA1UE\r\n" \ +"CgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0GCAQAwDAYDVR0T\r\n" \ +"BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAHK/HHrTZMnnVMpde1io+voAtql7j\r\n" \ +"4sRhLrjD7o3THtwRbDa2diCvpq0Sq23Ng2LMYoXsOxoL/RQK3iN7UKxV3MKPEr0w\r\n" \ +"XQS+kKQqiT2bsfrjnWMVHZtUOMpm6FNqcdGm/Rss3vKda2lcKl8kUnq/ylc1+QbB\r\n" \ +"G6A6tUvQcr2ZyWfVg+mM5XkhTrOOXus2OLikb4WwEtJTJRNE0f+yPODSUz0/vT57\r\n" \ +"ApH0CnB80bYJshYHPHHymOtleAB8KSYtqm75g/YNobjnjB6cm4HkW3OZRVIl6fYY\r\n" \ +"n20NRVA1Vjs6GAROr4NqW4k/+LofY9y0LLDE+p0oIEKXIsIvhPr39swxSA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA256; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#define TEST_CA_CRT_RSA_SOME + +static const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; + +#endif + +#if !defined(TEST_CA_CRT_RSA_SOME) || defined(MBEDTLS_SHA1_C) +#define TEST_CA_CRT_RSA_SHA1 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ +"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ +"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ +"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ +"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ +"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ +"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ +"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ +"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +#if !defined (TEST_CA_CRT_RSA_SOME) +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA1; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#endif + +static const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; + +#endif + +const char mbedtls_test_ca_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" +"\r\n" +"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" +"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" +"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" +"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" +"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" +"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" +"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" +"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" +"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" +"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" +"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" +"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" +"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" +"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" +"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" +"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" +"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" +"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" +"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" +"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" +"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" +"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" +"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" +"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" +"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); + +const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; + +const char mbedtls_test_srv_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" +"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" +"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" +"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" +"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" +"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" +"zhuYwjVuX6JHG0c=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); + +const char mbedtls_test_srv_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" +"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" +"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" +"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" +"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" +"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" +"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" +"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" +"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" +"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" +"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" +"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" +"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" +"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" +"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" +"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" +"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" +"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" +"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" +"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" +"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" +"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" +"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" +"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" +"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); + +const char mbedtls_test_cli_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" +"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" +"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" +"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" +"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" +"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" +"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" +"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n" +"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n" +"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n" +"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n" +"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n" +"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n" +"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n" +"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n" +"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); + +const char mbedtls_test_cli_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" +"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" +"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" +"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" +"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" +"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" +"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" +"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" +"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" +"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" +"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" +"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" +"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" +"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" +"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" +"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" +"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" +"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" +"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" +"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" +"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" +"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" +"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" +"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" +"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all available CA certificates */ +const char mbedtls_test_cas_pem[] = +#ifdef TEST_CA_CRT_RSA_SHA1 + TEST_CA_CRT_RSA_SHA1 +#endif +#ifdef TEST_CA_CRT_RSA_SHA256 + TEST_CA_CRT_RSA_SHA256 +#endif +#ifdef TEST_CA_CRT_EC + TEST_CA_CRT_EC +#endif + ""; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif + +/* List of all available CA certificates */ +const char * mbedtls_test_cas[] = { +#if defined(TEST_CA_CRT_RSA_SHA1) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + mbedtls_test_ca_crt_rsa_sha256, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(TEST_CA_CRT_RSA_SHA1) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +#if defined(MBEDTLS_RSA_C) +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; /* SHA1 or SHA256 */ +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); +#else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_CERTS_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/cipher.c ************/ + +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CIPHER_C) + + + + +#include +#include + +#if defined(MBEDTLS_GCM_C) + +#endif + +#if defined(MBEDTLS_CCM_C) + +#endif + +#if defined(MBEDTLS_CMAC_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + } + + if( MBEDTLS_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) +{ + size_t actual_iv_size; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + size_t block_size = 0; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + + if ( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + if( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + copy_len = ilen % block_size; + if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) + copy_len = block_size; + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i - 1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) +{ + if( NULL == ctx || + MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || + MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + size_t finish_olen; + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#endif /* MBEDTLS_CIPHER_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/cipher_wrap.c ************/ + +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CIPHER_C) + + + +#if defined(MBEDTLS_AES_C) + +#endif + +#if defined(MBEDTLS_ARC4_C) + +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#endif + +#if defined(MBEDTLS_DES_C) + +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#endif + +#if defined(MBEDTLS_GCM_C) + +#endif + +#if defined(MBEDTLS_CCM_C) + +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + //#define mbedtls_calloc calloc ////modified by ljy 20220330 + mbedtls_aes_context *aes = calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + //#define mbedtls_calloc free ////modified by ljy 20220330 + + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 16, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 16, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 8, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 8, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 8, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/cmac.c ************/ + +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CMAC_C) + + + +#include + + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char *output ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 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 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); + } + + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ctr_drbg.c ************/ + +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * 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) + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + + + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow + * NIST tests to succeed (which require known length fixed entropy) + */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len, + size_t entropy_len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->entropy_len = entropy_len; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, + MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + int ret = 0; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + int ret = 0; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) + { + return( ret ); + } + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + return( 0 ); +} + +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + + if( add_len > 0 ) + { + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* + * Gather entropy_len bytes of entropy to seed state + */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, + ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len; + + /* + * Add additional data + */ + if( additional && len ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* + * Reduce to 384 bits + */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + { + return( ret ); + } + + /* + * Update state + */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + { + return( ret ); + } + ctx->reseed_counter = 1; + + return( 0 ); +} + +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { + return( ret ); + } + add_len = 0; + } + + if( add_len > 0 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + { + return( ret ); + } + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + { + return( ret ); + } + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) + { + return( ret ); + } + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : + output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + { + return( ret ); + } + + ctx->reseed_counter++; + + return( 0 ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + else + ret = 0; + +exit: + mbedtls_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + fclose( f ); + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + else + mbedtls_ctr_drbg_update( ctx, buf, n ); + + fclose( f ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char entropy_source_pr[96] = + { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, + 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, + 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, + 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, + 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, + 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, + 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, + 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, + 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, + 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, + 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, + 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; + +static const unsigned char entropy_source_nopr[64] = + { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, + 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, + 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, + 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, + 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, + 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, + 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, + 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; + +static const unsigned char nonce_pers_pr[16] = + { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, + 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; + +static const unsigned char nonce_pers_nopr[16] = + { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, + 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; + +static const unsigned char result_pr[16] = + { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, + 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; + +static const unsigned char result_nopr[16] = + { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, + 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[16]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/debug.c ************/ + +/* + * Debugging routines + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#endif + + + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret; + + if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) + return; + + va_start( argp, format ); +#if defined(_WIN32) +#if defined(_TRUNCATE) && !defined(__MINGW32__) + ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); +#else + ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); + if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) + { + str[DEBUG_BUF_SIZE-1] = '\0'; + ret = -1; + } +#endif +#else + ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); +#endif + va_end( argp ); + + if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) + { + str[ret] = '\n'; + str[ret + 1] = '\0'; + } + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[DEBUG_BUF_SIZE]; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + return; + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if( ret == MBEDTLS_ERR_SSL_WANT_READ ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", + text, ret, -ret ); + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + return; + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", + (unsigned int) buf[i] ); + txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; + } + + if( len > 0 ) + { + for( /* i = i */; i % 16 != 0; i++ ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ) +{ + char str[DEBUG_BUF_SIZE]; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); + + mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ) +{ + char str[DEBUG_BUF_SIZE]; + int j, k, zeros = 1; + size_t i, n, idx = 0; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold ) + return; + + for( n = X->n - 1; n > 0; n-- ) + if( X->p[n] != 0 ) + break; + + for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) + if( ( ( X->p[n] >> j ) & 1 ) != 0 ) + break; + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", + text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + for( i = n + 1, j = 0; i > 0; i-- ) + { + if( zeros && X->p[i - 1] == 0 ) + continue; + + for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) + { + if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) + continue; + else + zeros = 0; + + if( j % 16 == 0 ) + { + if( j > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + idx = 0; + } + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) + ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); + + j++; + } + + } + + if( zeros == 1 ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk ) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( mbedtls_pk_debug( pk, items ) != 0 ) + { + debug_send_line( ssl, level, file, line, + "invalid PK context\n" ); + return; + } + + for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) + return; + + mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) + mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(MBEDTLS_ECP_C) + if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) + mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_send_line( ssl, level, file, line, + "should not happen\n" ); + } +} + +static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for( cur = text; *cur != '\0'; cur++ ) + { + if( *cur == '\n' ) + { + size_t len = cur - start + 1; + if( len > DEBUG_BUF_SIZE - 1 ) + len = DEBUG_BUF_SIZE - 1; + + memcpy( str, start, len ); + str[len] = '\0'; + + debug_send_line( ssl, level, file, line, str ); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold ) + return; + + while( crt != NULL ) + { + char buf[1024]; + + mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); + debug_send_line( ssl, level, file, line, str ); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + debug_print_line_by_line( ssl, level, file, line, buf ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#endif /* MBEDTLS_DEBUG_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/des.c ************/ + +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * 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) + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_DES_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_DES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + GET_UINT32_BE( X, key, 0 ); + GET_UINT32_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des3_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, + { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, + { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, + { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, + { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, + { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, + { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, + { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, + { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/dhm.c ************/ + +/* + * Diffie-Hellman-Merkle key exchange + * + * 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) + */ +/* + * The following sources were referenced in the design of this implementation + * of the Diffie-Hellman-Merkle algorithm: + * + * [1] Handbook of Applied Cryptography - 1997, Chapter 12 + * Menezes, van Oorschot and Vanstone + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_DHM_C) + + + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_DHM_ALT) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * helper to validate the mbedtls_mpi size and import it + */ +static int dhm_read_bignum( mbedtls_mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * This means that we need to return an error if + * public_param < 2 or public_param > P-2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) +{ + mbedtls_mpi L, U; + int ret = 0; + + mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); + + if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || + mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) + { + ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + +cleanup: + mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mbedtls_mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + size_t n1, n2, n3; + unsigned char *p; + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + /* + * export P, G, GX + */ +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = (unsigned char)( ( n ) >> 8 ); \ + *p++ = (unsigned char)( ( n ) ); \ + p += ( n ); \ + } while( 0 ) + + n1 = mbedtls_mpi_size( &ctx->P ); + n2 = mbedtls_mpi_size( &ctx->G ); + n3 = mbedtls_mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + + ctx->len = n1; + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); + + return( 0 ); +} + +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret; + + if( ctx == NULL || P == NULL || G == NULL ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->P ); + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret; + + if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + + if( ctx == NULL || olen < 1 || olen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-1 ) */ + count = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + + /* Vf = Vi^-X mod P */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi GYb; + + if( ctx == NULL || output_size < ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mbedtls_mpi_size( &ctx->K ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + } + + ret = 0; + + dhm->len = mbedtls_mpi_size( &dhm->P ); + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_zeroize( *buf, *n + 1 ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_DHM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const char mbedtls_test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; + +static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); + +/* + * Checkup routine + */ +int mbedtls_dhm_self_test( int verbose ) +{ + int ret; + mbedtls_dhm_context dhm; + + mbedtls_dhm_init( &dhm ); + + if( verbose != 0 ) + mbedtls_printf( " DHM parameter load: " ); + + if( ( ret = mbedtls_dhm_parse_dhm( &dhm, + (const unsigned char *) mbedtls_test_dhm_params, + mbedtls_test_dhm_params_len ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + +exit: + mbedtls_dhm_free( &dhm ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DHM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecdh.c ************/ + +/* + * Elliptic curve Diffie-Hellman + * + * 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) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ECDH_C) + + + +#include + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) +/* + * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); +} +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point P; + + mbedtls_ecp_point_init( &P ); + + /* + * Make sure Q is a valid pubkey before using it + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + + if( mbedtls_ecp_is_zero( &P ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); + +cleanup: + mbedtls_ecp_point_free( &P ); + + return( ret ); +} +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +/* + * Initialize context + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); +} + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_mpi_free( &ctx->z ); + mbedtls_mpi_free( &ctx->_d ); +} + +/* + * Setup and write the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t grp_len, pt_len; + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) + != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Read the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ) +{ + int ret; + + if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) + != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) + return( ret ); + + /* If it's not our key, just import the public part as Qp */ + if( side == MBEDTLS_ECDH_THEIRS ) + return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != MBEDTLS_ECDH_OURS ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Setup and export the client public value + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + olen, buf, blen ); +} + +/* + * Parse and import the client's public value + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret; + const unsigned char *p = buf; + + if( ctx == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ctx == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_mpi_size( &ctx->z ) > blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); +} + +#endif /* MBEDTLS_ECDH_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecdsa.c ************/ + +/* + * Elliptic curve DSA + * + * 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) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ECDSA_C) + + + + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + +#endif + +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, key_tries, sign_tries, blind_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + sign_tries = 0; + do + { + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + key_tries = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); + + if( key_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + blind_tries = 0; + do + { + size_t n_size = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); + + /* See mbedtls_ecp_gen_keypair() */ + if( ++blind_tries > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + + if( sign_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + int ret; + mbedtls_hmac_drbg_context rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); + + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, &rng_ctx ); + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +{ + int ret; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Additional precaution: make sure Q is valid + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); + + /* + * Step 5: R = u1 G + u2 Q + * + * Since we're not using any secret data, no need to pass a RNG to + * mbedtls_ecp_mul() for countermesures. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi r, s; + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + (void) f_rng; + (void) p_rng; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg ) ); +#else + (void) md_alg; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#endif + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ + defined(MBEDTLS_ECDSA_DETERMINISTIC) +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) +{ + return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, + NULL, NULL ) ); +} +#endif + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + int ret; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; + + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecp_group_load( &ctx->grp, gid ) || + mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); +} +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + mbedtls_ecp_keypair_free( ctx ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecjpake.c ************/ + +/* + * Elliptic curve J-PAKE + * + * 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) + */ + +/* + * References in the code are to the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ECJPAKE_C) + + + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* + * Convert a mbedtls_ecjpake_role to identifier string + */ +static const char * const ecjpake_id[] = { + "client", + "server" +}; + +#define ID_MINE ( ecjpake_id[ ctx->role ] ) +#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) + +/* + * Initialize context + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_init( &ctx->grp ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + + mbedtls_ecp_point_init( &ctx->Xm1 ); + mbedtls_ecp_point_init( &ctx->Xm2 ); + mbedtls_ecp_point_init( &ctx->Xp1 ); + mbedtls_ecp_point_init( &ctx->Xp2 ); + mbedtls_ecp_point_init( &ctx->Xp ); + + mbedtls_mpi_init( &ctx->xm1 ); + mbedtls_mpi_init( &ctx->xm2 ); + mbedtls_mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_free( &ctx->grp ); + + mbedtls_ecp_point_free( &ctx->Xm1 ); + mbedtls_ecp_point_free( &ctx->Xm2 ); + mbedtls_ecp_point_free( &ctx->Xp1 ); + mbedtls_ecp_point_free( &ctx->Xp2 ); + mbedtls_ecp_point_free( &ctx->Xp ); + + mbedtls_mpi_free( &ctx->xm1 ); + mbedtls_mpi_free( &ctx->xm2 ); + mbedtls_mpi_free( &ctx->s ); +} + +/* + * Setup context + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ) +{ + int ret; + + ctx->role = role; + + if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); + +cleanup: + if( ret != 0 ) + mbedtls_ecjpake_free( ctx ); + + return( ret ); +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) +{ + if( ctx->md_info == NULL || + ctx->grp.id == MBEDTLS_ECP_DP_NONE || + ctx->s.p == NULL ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Write a point plus its length to a buffer + */ +static int ecjpake_write_len_point( unsigned char **p, + const unsigned char *end, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *P ) +{ + int ret; + size_t len; + + /* Need at least 4 for length plus 1 for point */ + if( end < *p || end - *p < 5 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + ret = mbedtls_ecp_point_write_binary( grp, P, pf, + &len, *p + 4, end - ( *p + 4 ) ); + if( ret != 0 ) + return( ret ); + + (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); + (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); + (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); + (*p)[3] = (unsigned char)( ( len ) & 0xFF ); + + *p += 4 + len; + + return( 0 ); +} + +/* + * Size of the temporary buffer for ecjpake_hash: + * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) + */ +#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) + +/* + * Compute hash for ZKP (7.4.2.2.2.1) + */ +static int ecjpake_hash( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *V, + const mbedtls_ecp_point *X, + const char *id, + mbedtls_mpi *h ) +{ + int ret; + unsigned char buf[ECJPAKE_HASH_BUF_LEN]; + unsigned char *p = buf; + const unsigned char *end = buf + sizeof( buf ); + const size_t id_len = strlen( id ); + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Write things to temporary buffer */ + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); + + if( end - p < 4 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len ) & 0xFF ); + + if( end < p || (size_t)( end - p ) < id_len ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( p, id, id_len ); + p += id_len; + + /* Compute hash */ + mbedtls_md( md_info, buf, p - buf, hash ); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, + mbedtls_md_get_size( md_info ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) + */ +static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret; + mbedtls_ecp_point V, VV; + mbedtls_mpi r, h; + size_t r_len; + + mbedtls_ecp_point_init( &V ); + mbedtls_ecp_point_init( &VV ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &h ); + + /* + * struct { + * ECPoint V; + * opaque r<1..2^8-1>; + * } ECSchnorrZKP; + */ + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); + + if( end < *p || (size_t)( end - *p ) < 1 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + r_len = *(*p)++; + + if( end < *p || (size_t)( end - *p ) < r_len ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); + *p += r_len; + + /* + * Verification + */ + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, + &VV, &h, X, &r, G ) ); + + if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_ecp_point_free( &VV ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) + */ +static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_mpi *x, + const mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point V; + mbedtls_mpi v; + mbedtls_mpi h; /* later recycled to hold r */ + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &V ); + mbedtls_mpi_init( &v ); + mbedtls_mpi_init( &h ); + + /* Compute signature */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, + G, &v, &V, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ + + /* Write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, + pf, &len, *p, end - *p ) ); + *p += len; + + len = mbedtls_mpi_size( &h ); /* actually r */ + if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + *(*p)++ = (unsigned char)( len & 0xFF ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ + *p += len; + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_mpi_free( &v ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof + * Output: verified public key X + */ +static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * struct { + * ECPoint X; + * ECSchnorrZKP zkp; + * } ECJPAKEKeyKP; + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); + if( mbedtls_ecp_is_zero( X ) ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); + +cleanup: + return( ret ); +} + +/* + * Generate an ECJPAKEKeyKP + * Output: the serialized structure, plus private/public key pair + */ +static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *x, + mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* Generate key (7.4.2.3.1) and write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, + pf, &len, *p, end - *p ) ); + *p += len; + + /* Generate and write proof */ + MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, + p, end, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs + * Ouputs: verified peer public keys Xa, Xb + */ +static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *Xa, + mbedtls_ecp_point *Xb, + const char *id, + const unsigned char *buf, + size_t len ) +{ + int ret; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + /* + * struct { + * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; + * } ECJPAKEKeyKPPairList; + */ + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); + + if( p != end ) + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + +cleanup: + return( ret ); +} + +/* + * Generate a ECJPAKEKeyKPPairList + * Outputs: the serialized structure, plus two private/public key pairs + */ +static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *xm1, + mbedtls_ecp_point *Xa, + mbedtls_mpi *xm2, + mbedtls_ecp_point *Xb, + const char *id, + unsigned char *buf, + size_t len, + size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = buf + len; + + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + return( ret ); +} + +/* + * Read and process the first round message + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->Xp1, &ctx->Xp2, ID_PEER, + buf, len ) ); +} + +/* + * Generate and write the first round message + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, + ID_MINE, buf, len, olen, f_rng, p_rng ) ); +} + +/* + * Compute the sum of three points R = A + B + C + */ +static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *A, + const mbedtls_ecp_point *B, + const mbedtls_ecp_point *C ) +{ + int ret; + mbedtls_mpi one; + + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); + +cleanup: + mbedtls_mpi_free( &one ); + + return( ret ); +} + +/* + * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + int ret; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + mbedtls_ecp_group grp; + mbedtls_ecp_point G; /* C: GB, S: GA */ + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &G ); + + /* + * Server: GA = X3 + X4 + X1 (7.4.2.6.1) + * Client: GB = X1 + X2 + X3 (7.4.2.5.1) + * Unified: G = Xm1 + Xm2 + Xp1 + * We need that before parsing in order to check Xp as we read it + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); + + /* + * struct { + * ECParameters curve_params; // only client reading server msg + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); + if( grp.id != ctx->grp.id ) + { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &ctx->Xp, ID_PEER, &p, end ) ); + + if( p != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &G ); + + return( ret ); +} + +/* + * Compute R = +/- X * S mod N, taking care not to leak S + */ +static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, + const mbedtls_mpi *X, + const mbedtls_mpi *S, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi b; /* Blinding value, then s + N * blinding */ + + mbedtls_mpi_init( &b ); + + /* b = s + rnd-128-bit * N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); + + /* R = sign * X * b mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); + R->s *= sign; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); + +cleanup: + mbedtls_mpi_free( &b ); + + return( ret ); +} + +/* + * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point G; /* C: GA, S: GB */ + mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ + mbedtls_mpi xm; /* C: xc, S: xs */ + unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t ec_len; + + mbedtls_ecp_point_init( &G ); + mbedtls_ecp_point_init( &Xm ); + mbedtls_mpi_init( &xm ); + + /* + * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) + * + * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA + * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB + * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); + + /* + * Now write things out + * + * struct { + * ECParameters curve_params; // only server writing its message + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) + { + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, + p, end - p ) ); + p += ec_len; + } + + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, + ctx->point_format, &ec_len, p, end - p ) ); + p += ec_len; + + MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &xm, &Xm, ID_MINE, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + mbedtls_ecp_point_free( &G ); + mbedtls_ecp_point_free( &Xm ); + mbedtls_mpi_free( &xm ); + + return( ret ); +} + +/* + * Derive PMS (7.4.2.7 / 7.4.2.8) + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point K; + mbedtls_mpi m_xm2_s, one; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + *olen = mbedtls_md_get_size( ctx->md_info ); + if( len < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &K ); + mbedtls_mpi_init( &m_xm2_s ); + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + + /* + * Client: K = ( Xs - X4 * x2 * s ) * x2 + * Server: K = ( Xc - X2 * x4 * s ) * x4 + * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 + */ + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, + &one, &ctx->Xp, + &m_xm2_s, &ctx->Xp2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, + f_rng, p_rng ) ); + + /* PMS = SHA-256( K.X ) */ + x_bytes = ( ctx->grp.pbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); + +cleanup: + mbedtls_ecp_point_free( &K ); + mbedtls_mpi_free( &m_xm2_s ); + mbedtls_mpi_free( &one ); + + return( ret ); +} + +#undef ID_MINE +#undef ID_PEER + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + !defined(MBEDTLS_SHA256_C) +int mbedtls_ecjpake_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +static const unsigned char ecjpake_test_password[] = { + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, + 0x65, 0x73, 0x74 +}; + +static const unsigned char ecjpake_test_x1[] = { + 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, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 +}; + +static const unsigned char ecjpake_test_x2[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x3[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x4[] = { + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, + 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 +}; + +static const unsigned char ecjpake_test_cli_one[] = { + 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, + 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, + 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, + 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, + 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, + 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, + 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, + 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, + 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, + 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, + 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, + 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, + 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, + 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, + 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, + 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, + 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, + 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, + 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, + 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, + 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, + 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, + 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, + 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, + 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, + 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, + 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, + 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 +}; + +static const unsigned char ecjpake_test_srv_one[] = { + 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, + 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, + 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, + 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, + 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, + 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, + 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, + 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, + 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, + 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, + 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, + 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, + 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, + 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, + 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, + 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, + 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, + 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, + 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, + 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, + 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, + 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, + 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, + 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, + 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, + 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, + 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, + 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 +}; + +static const unsigned char ecjpake_test_srv_two[] = { + 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, + 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, + 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, + 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, + 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, + 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, + 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, + 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, + 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, + 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, + 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, + 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, + 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, + 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c +}; + +static const unsigned char ecjpake_test_cli_two[] = { + 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, + 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, + 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, + 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, + 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, + 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, + 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, + 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, + 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, + 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, + 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, + 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, + 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, + 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c +}; + +static const unsigned char ecjpake_test_pms[] = { + 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, + 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, + 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 +}; + +/* Load my private keys and generate the correponding public keys */ +static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, + const unsigned char *xm1, size_t len1, + const unsigned char *xm2, size_t len2 ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, + &ctx->grp.G, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, NULL, NULL ) ); + +cleanup: + return( ret ); +} + +/* For tests we don't need a secure RNG; + * use the LGC from Numerical Recipes for simplicity */ +static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) +{ + static uint32_t x = 42; + (void) p; + + while( len > 0 ) + { + size_t use_len = len > 4 ? 4 : len; + x = 1664525 * x + 1013904223; + memcpy( out, &x, use_len ); + out += use_len; + len -= use_len; + } + + return( 0 ); +} + +#define TEST_ASSERT( x ) \ + do { \ + if( x ) \ + ret = 0; \ + else \ + { \ + ret = 1; \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * Checkup routine + */ +int mbedtls_ecjpake_self_test( int verbose ) +{ + int ret; + mbedtls_ecjpake_context cli; + mbedtls_ecjpake_context srv; + unsigned char buf[512], pms[32]; + size_t len, pmslen; + + mbedtls_ecjpake_init( &cli ); + mbedtls_ecjpake_init( &srv ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #0 (setup): " ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == pmslen ); + TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); + + /* Simulate generation of round one */ + MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, + ecjpake_test_x1, sizeof( ecjpake_test_x1 ), + ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); + + MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, + ecjpake_test_x3, sizeof( ecjpake_test_x3 ), + ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); + + /* Read round one */ + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, + ecjpake_test_cli_one, + sizeof( ecjpake_test_cli_one ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, + ecjpake_test_srv_one, + sizeof( ecjpake_test_srv_one ) ) == 0 ); + + /* Skip generation of round two, read round two */ + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, + ecjpake_test_srv_two, + sizeof( ecjpake_test_srv_two ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, + ecjpake_test_cli_two, + sizeof( ecjpake_test_cli_two ) ) == 0 ); + + /* Server derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + memset( buf, 0, len ); /* Avoid interferences with next step */ + + /* Client derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_ecjpake_free( &cli ); + mbedtls_ecjpake_free( &srv ); + + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#undef TEST_ASSERT + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECJPAKE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecp.c ************/ + +/* + * Elliptic curves over GF(p): generic functions + * + * 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) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ECP_C) + + + + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define ECP_SHORTWEIERSTRASS +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + ECP_TYPE_NONE = 0, + ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} ecp_curve_type; + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( ECP_TYPE_MONTGOMERY ); + else + return( ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + if( grp == NULL ) + return; + + memset( grp, 0, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + return mbedtls_ecp_group_load( dst, src->id ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazyly + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + + if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + return mbedtls_ecp_group_load( grp, curve_info->grp_id ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ + while( 0 ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi Zi, ZZi; + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_jac( grp, pt ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ) +{ + int ret; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( t_len < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); + } +#endif + + if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < t_len; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + + for( i = t_len - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < t_len; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret; + mbedtls_mpi M, S, T, U; + +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_double_jac( grp, R, P ); + } +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); + } +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l, ll; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries. + * + * Also, for the sake of compactness, only the seven low-order bits of x[i] + * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in + * the paper): it is set if and only if if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_fixed( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the comb method + * + * If i = i_{w-1} ... i_1 is the binary representation of i, then + * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * + * T must be able to hold 2^{w - 1} elements + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d ) +{ + int ret; + unsigned char i, k; + size_t j; + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + cur = T + i; + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + for( j = 0; j < d; j++ ) + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + TT[k++] = cur; + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + j = i; + while( j-- ) + { + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + TT[k++] = &T[i + j]; + } + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + +cleanup: + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + unsigned char i ) +{ + int ret; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < t_len; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + + while( i-- != 0 ) + { + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + + return( ret ); +} + +/* + * Multiplication using the comb method, + * for curves in short Weierstrass form + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char w, m_is_odd, p_eq_g, pre_len, i; + size_t d; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *T; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* we need N to be odd to trnaform m in an odd number, check now */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); + if( p_eq_g ) + w++; +#else + p_eq_g = 0; +#endif + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + /* Other sizes that depend on w */ + pre_len = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* + * Prepare precomputed points: if P == G we want to + * use grp->T if already initialized, or initialize it. + */ + T = p_eq_g ? grp->T : NULL; + + if( T == NULL ) + { + T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + + if( p_eq_g ) + { + grp->T = T; + grp->T_size = pre_len; + } + } + + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + + /* + * Go for comb multiplication, R = M * P + */ + ecp_comb_fixed( k, d, w, &M ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + + /* + * Now get m * P from M * P and normalize it + */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + if( T != NULL && ! p_eq_g ) + { + for( i = 0; i < pre_len; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + mbedtls_mpi_free( &M ); + mbedtls_mpi_free( &mm ); + + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + return( ret ); +} + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ + int ret; + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_mxz( grp, P ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + mbedtls_mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ + int ret; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); + } +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; + + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ + if( f_rng != NULL ) + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* ECP_MONTGOMERY */ + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + + /* Common sanity checks */ + if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || + ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); + +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); + +#endif +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +cleanup: + + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + return( ret ); +} + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* ECP_SHORTWEIERSTRASS */ + +/* + * R = m * P with shortcuts for m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + } + +cleanup: + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_ecp_point mP; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + mbedtls_ecp_point_free( &mP ); + + return( ret ); +} + + +#if defined(ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) +{ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* see [Curve25519] page 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_get_bit( d, 2 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); + + /* Make sure the most significant bit is nbits */ + b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ + if( b > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last three bits are unset */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + else +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + + /* + * Match the procedure given in RFC 6979 (deterministic ECDSA): + * - use the same byte ordering; + * - keep the leftmost nbits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any biais, which is especially important for ECDSA. + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); + } + else +#endif /* ECP_SHORTWEIERSTRASS */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret; + size_t i; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + /* exponents especially adapted for secp192r1 */ + const char *exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ecp_curves.c ************/ + +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ECP_C) + + + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) | \ + ( (mbedtls_mpi_uint) e << 32 ) | \ + ( (mbedtls_mpi_uint) f << 40 ) | \ + ( (mbedtls_mpi_uint) g << 48 ) | \ + ( (mbedtls_mpi_uint) h << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionaly not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + + default: + mbedtls_ecp_group_free( grp ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + i * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = b; \ + mbedtls_mpi C; \ + mbedtls_mpi_uint Cp[ b / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = b / 8 / sizeof( mbedtls_mpi_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ + \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, b * 2 / 8 / sizeof( mbedtls_mpi_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) fix_negative( N, c, &C, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(MBEDTLS_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; + + /* N = - ( C - N ) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + M.n = P255_WIDTH + 1; + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/entropy.c ************/ + +/* + * Entropy accumulator implementation + * + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + + + + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = 0; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret, i, have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, done; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + done = 1; + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size < ctx->source[i].threshold ) + done = 0; + } + while( ! done ); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: + mbedtls_zeroize( buf, sizeof( buf ) ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + mbedtls_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/entropy_poll.c ************/ + +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ENTROPY_C) + + + + +#if defined(MBEDTLS_TIMING_C) +#include + +#endif +#if defined(MBEDTLS_HAVEGE_C) + +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include +/* Check if version is at least 3.17.0 */ +static int check_version_3_17_plus( void ) +{ + int minor; + struct utsname un; + const char *ver; + + /* Get version information */ + uname(&un); + ver = un.release; + + /* Check major version; assume a single digit */ + if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) + return( -1 ); + + if( ver[0] - '0' > 3 ) + return( 0 ); + + /* Ok, so now we know major == 3, check minor. + * Assume 1 or 2 digits. */ + if( ver[2] < '0' || ver[2] > '9' ) + return( -1 ); + + minor = ver[2] - '0'; + + if( ver[3] >= '0' && ver[3] <= '9' ) + minor = 10 * minor + ver[3] - '0'; + else if( ver [3] != '.' ) + return( -1 ); + + if( minor < 17 ) + return( -1 ); + + return( 0 ); +} +static int has_getrandom = -1; +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + ((void) data); + +#if defined(HAVE_GETRANDOM) + if( has_getrandom == -1 ) + has_getrandom = ( check_version_3_17_plus() == 0 ); + + if( has_getrandom ) + { + int ret; + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/error.c ************/ + +/* + * Error message information + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_snprintf snprintf +#define mbedtls_time_t time_t +#endif + +#if defined(MBEDTLS_ERROR_C) + +#include + +#if defined(MBEDTLS_AES_C) + +#endif + +#if defined(MBEDTLS_ARC4_C) + +#endif + +#if defined(MBEDTLS_BASE64_C) + +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#endif + +#if defined(MBEDTLS_CCM_C) + +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#endif + +#if defined(MBEDTLS_CMAC_C) + +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#endif + +#if defined(MBEDTLS_DES_C) + +#endif + +#if defined(MBEDTLS_DHM_C) + +#endif + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#endif + +#if defined(MBEDTLS_GCM_C) + +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#endif + +#if defined(MBEDTLS_MD_C) + +#endif + +#if defined(MBEDTLS_MD2_C) + +#endif + +#if defined(MBEDTLS_MD4_C) + +#endif + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_NET_C) + +#endif + +#if defined(MBEDTLS_OID_C) + +#endif + +#if defined(MBEDTLS_PADLOCK_C) + +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#endif + +#if defined(MBEDTLS_PK_C) + +#endif + +#if defined(MBEDTLS_PKCS12_C) + +#endif + +#if defined(MBEDTLS_PKCS5_C) + +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#endif + +#if defined(MBEDTLS_RSA_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#endif + +#if defined(MBEDTLS_XTEA_C) + +#endif + + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_CIPHER_C) + if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid. For example, because it was freed" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "DHM - Read or write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); + if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) + mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); + if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - ECP hardware accelerator failed" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); + if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) + mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) + mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) + mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) + mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); + if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the validity check of the library" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); + if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) ) + mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) + mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) + mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) + mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) + mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) + mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) + mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) + mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) + mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) + mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) + mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) + mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) + mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) + mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) + mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) + mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); + if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_AES_C) + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); + if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) + mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); + if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); + if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); + if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to the function" ); + if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CMAC_C) + if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The requested random buffer length is too big" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_GCM_C) + if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_MD2_C) + if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_NET_C) + if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) + mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); + if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) + mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); + if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) + mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_THREADING_C) + if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) + mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); +#endif /* MBEDTLS_XTEA_C */ + // END generated code + + if( strlen( buf ) != 0 ) + return; + + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#else /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ + +#endif /* MBEDTLS_ERROR_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/gcm.c ************/ + +/* + * NIST SP800-38D compliant GCM implementation + * + * 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) + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_GCM_C) + + + +#include + +#if defined(MBEDTLS_AESNI_C) + +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_GCM_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + PUT_UINT32_BE( ctx->HH[8], h, 4 ); + PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if( iv_len == 0 || + ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + if( output > input && (size_t) ( output - input ) < length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len = ctx->len * 8; + uint64_t orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret; + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#endif /* !MBEDTLS_GCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +static const int key_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char key[MAX_TESTS][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +static const size_t iv_len[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +static const int iv_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +static const unsigned char iv[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b }, +}; + +static const size_t add_len[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +static const int add_index[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +static const unsigned char additional[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +static const size_t pt_len[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +static const int pt_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char pt[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, +}; + +static const unsigned char ct[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91 }, + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98 }, + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +static const unsigned char tag[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int mbedtls_gcm_self_test( int verbose ) +{ + mbedtls_gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + pt[pt_index[i]], buf, 16, tag_buf ); + if( ret != 0 ) + goto exit; + + if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + ct[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/havege.c ************/ + +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * 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) + */ +/* + * The HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_HAVEGE_C) + + + + +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (int) mbedtls_timing_hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (int) mbedtls_timing_hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( mbedtls_havege_state *hs ) +{ + int i, n = 0; + int U1, U2, *A, *B, *C, *D; + int PT1, PT2, *WALK, RES[16]; + int PTX, PTY, CLK, PTEST, IN; + + WALK = hs->WALK; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + (void)PTX; + + memset( RES, 0, sizeof( RES ) ); + + while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ) +{ + memset( hs, 0, sizeof( mbedtls_havege_state ) ); + + havege_fill( hs ); +} + +void mbedtls_havege_free( mbedtls_havege_state *hs ) +{ + if( hs == NULL ) + return; + + mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + int val; + size_t use_len; + mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; + unsigned char *p = buf; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) + havege_fill( hs ); + + val = hs->pool[hs->offset[0]++]; + val ^= hs->pool[hs->offset[1]++]; + + memcpy( p, &val, use_len ); + + len -= use_len; + p += use_len; + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVEGE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/hmac_drbg.c ************/ + +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * 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) + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + + + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + mbedtls_md_hmac_reset( &ctx->md_ctx ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( rounds == 2 ) + mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, K ); + + /* Step 2 or 5 */ + mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + } +} + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + mbedtls_hmac_drbg_update( ctx, data, data_len ); + + return( 0 ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + + seedlen = ctx->entropy_len; + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + mbedtls_hmac_drbg_update( ctx, seed, seedlen ); + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + + /* 4. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + size_t entropy_len, md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; + + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + + /* + * For initialisation, use more entropy to emulate a nonce + * (Again, matches test vectors.) + */ + ctx->entropy_len = entropy_len * 3 / 2; + + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + ctx->entropy_len = entropy_len; + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for reseeds + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + mbedtls_hmac_drbg_update( ctx, additional, add_len ); + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + mbedtls_md_hmac_reset( &ctx->md_ctx ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + mbedtls_hmac_drbg_update( ctx, additional, add_len ); + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + + /* 8. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free an HMAC_DRBG context + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + { + fclose( f ); + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + else + mbedtls_hmac_drbg_update( ctx, buf, n ); + + fclose( f ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md.c ************/ + +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_MD_C) + + + + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + md_info->ctx_free_func( ctx->md_ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + ctx->md_info = md_info; + + return( 0 ); +} + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->starts_func( ctx->md_ctx ) ); +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( md_info->digest_func( input, ilen, output ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = md_info->finish_func( ctx.md_ctx, output ); + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + return( ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->process_func( ctx->md_ctx, data ) ); +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md2.c ************/ + +/* + * RFC 1115/1319 compliant MD2 implementation + * + * 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) + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_MD2_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD2_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void mbedtls_md2_init( mbedtls_md2_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_free( mbedtls_md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ) +{ + *dst = *src; +} + +/* + * MD2 context setup + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + mbedtls_md2_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD2_PROCESS_ALT) +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ) +{ + int i, j; + unsigned char t = 0; + + for( i = 0; i < 16; i++ ) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = + (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); + } + + for( i = 0; i < 18; i++ ) + { + for( j = 0; j < 48; j++ ) + { + ctx->state[j] = (unsigned char) + ( ctx->state[j] ^ PI_SUBST[t] ); + t = ctx->state[j]; + } + + t = (unsigned char)( t + i ); + } + + t = ctx->cksum[15]; + + for( i = 0; i < 16; i++ ) + { + ctx->cksum[i] = (unsigned char) + ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); + t = ctx->cksum[i]; + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + mbedtls_internal_md2_process( ctx ); +} +#endif +#endif /* !MBEDTLS_MD2_PROCESS_ALT */ + +/* + * MD2 process buffer + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + + while( ilen > 0 ) + { + if( ilen > 16 - ctx->left ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + } + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD2 final digest + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + int ret; + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( output, ctx->state, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md2_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md2_context ctx; + + mbedtls_md2_init( &ctx ); + + if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md2_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md2_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const unsigned char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md2_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md2_test_sum[7][16] = +{ + { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, + 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, + { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, + 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, + { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, + 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, + { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, + 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, + { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, + 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, + { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, + 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, + { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, + 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } +}; + +/* + * Checkup routine + */ +int mbedtls_md2_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD2 test #%d: ", i + 1 ); + + ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD2_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md4.c ************/ + +/* + * RFC 1186/1320 compliant MD4 implementation + * + * 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) + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_MD4_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD4_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md4_init( mbedtls_md4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_free( mbedtls_md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ) +{ + *dst = *src; +} + +/* + * MD4 context setup + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + mbedtls_md4_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD4_PROCESS_ALT) +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md4_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD4_PROCESS_ALT */ + +/* + * MD4 process buffer + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + + if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md4_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md4_context ctx; + + mbedtls_md4_init( &ctx ); + + if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md4_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md4_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const unsigned char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md4_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md4_test_sum[7][16] = +{ + { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, + 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, + { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, + 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, + { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, + 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, + { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, + 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, + { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, + 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, + { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, + 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, + { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, + 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } +}; + +/* + * Checkup routine + */ +int mbedtls_md4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD4 test #%d: ", i + 1 ); + + ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD4_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md5.c ************/ + +/* + * RFC 1321 compliant MD5 implementation + * + * 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) + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_MD5_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/md_wrap.c ************/ + +/** + * \file md_wrap.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_MD_C) + + + +#if defined(MBEDTLS_MD2_C) + +#endif + +#if defined(MBEDTLS_MD4_C) + +#endif + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_MD2_C) + +static int md2_starts_wrap( void *ctx ) +{ + return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) ); +} + +static int md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) ); +} + +static int md2_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) ); +} + +static void *md2_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); + + if( ctx != NULL ) + mbedtls_md2_init( (mbedtls_md2_context *) ctx ); + + return( ctx ); +} + +static void md2_ctx_free( void *ctx ) +{ + mbedtls_md2_free( (mbedtls_md2_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md2_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md2_clone( (mbedtls_md2_context *) dst, + (const mbedtls_md2_context *) src ); +} + +static int md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) ); +} + +const mbedtls_md_info_t mbedtls_md2_info = { + MBEDTLS_MD_MD2, + "MD2", + 16, + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + mbedtls_md2_ret, + md2_ctx_alloc, + md2_ctx_free, + md2_clone_wrap, + md2_process_wrap, +}; + +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + +static int md4_starts_wrap( void *ctx ) +{ + return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) ); +} + +static int md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) ); +} + +static int md4_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) ); +} + +static void *md4_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); + + if( ctx != NULL ) + mbedtls_md4_init( (mbedtls_md4_context *) ctx ); + + return( ctx ); +} + +static void md4_ctx_free( void *ctx ) +{ + mbedtls_md4_free( (mbedtls_md4_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md4_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md4_clone( (mbedtls_md4_context *) dst, + (const mbedtls_md4_context *) src ); +} + +static int md4_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_md4_info = { + MBEDTLS_MD_MD4, + "MD4", + 16, + 64, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + mbedtls_md4_ret, + md4_ctx_alloc, + md4_ctx_free, + md4_clone_wrap, + md4_process_wrap, +}; + +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + +static int md5_starts_wrap( void *ctx ) +{ + return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) ); +} + +static int md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) ); +} + +static int md5_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) ); +} + +static void *md5_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); + + if( ctx != NULL ) + mbedtls_md5_init( (mbedtls_md5_context *) ctx ); + + return( ctx ); +} + +static void md5_ctx_free( void *ctx ) +{ + mbedtls_md5_free( (mbedtls_md5_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md5_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md5_clone( (mbedtls_md5_context *) dst, + (const mbedtls_md5_context *) src ); +} + +static int md5_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_md5_info = { + MBEDTLS_MD_MD5, + "MD5", + 16, + 64, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + mbedtls_md5_ret, + md5_ctx_alloc, + md5_ctx_free, + md5_clone_wrap, + md5_process_wrap, +}; + +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + +static int ripemd160_starts_wrap( void *ctx ) +{ + return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) ); +} + +static int ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx, + input, ilen ) ); +} + +static int ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx, + output ) ); +} + +static void *ripemd160_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); + + if( ctx != NULL ) + mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); + mbedtls_free( ctx ); +} + +static void ripemd160_clone_wrap( void *dst, const void *src ) +{ + mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, + (const mbedtls_ripemd160_context *) src ); +} + +static int ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_ripemd160_process( + (mbedtls_ripemd160_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_ripemd160_info = { + MBEDTLS_MD_RIPEMD160, + "RIPEMD160", + 20, + 64, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + mbedtls_ripemd160_ret, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_clone_wrap, + ripemd160_process_wrap, +}; + +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + +static int sha1_starts_wrap( void *ctx ) +{ + return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) ); +} + +static int sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx, + input, ilen ) ); +} + +static int sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) ); +} + +static void *sha1_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); + + if( ctx != NULL ) + mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); + + return( ctx ); +} + +static void sha1_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, + (const mbedtls_sha1_context *) src ); +} + +static void sha1_ctx_free( void *ctx ) +{ + mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); + mbedtls_free( ctx ); +} + +static int sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha1_info = { + MBEDTLS_MD_SHA1, + "SHA1", + 20, + 64, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + mbedtls_sha1_ret, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_clone_wrap, + sha1_process_wrap, +}; + +#endif /* MBEDTLS_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(MBEDTLS_SHA256_C) + +static int sha224_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) ); +} + +static int sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx, + input, ilen ) ); +} + +static int sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx, + output ) ); +} + +static int sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); +} + +static void *sha224_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); + + if( ctx != NULL ) + mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); + + return( ctx ); +} + +static void sha224_ctx_free( void *ctx ) +{ + mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha224_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, + (const mbedtls_sha256_context *) src ); +} + +static int sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha224_info = { + MBEDTLS_MD_SHA224, + "SHA224", + 28, + 64, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +static int sha256_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) ); +} + +static int sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); +} + +const mbedtls_md_info_t mbedtls_sha256_info = { + MBEDTLS_MD_SHA256, + "SHA256", + 32, + 64, + sha256_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha256_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + +static int sha384_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) ); +} + +static int sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx, + input, ilen ) ); +} + +static int sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx, + output ) ); +} + +static int sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +} + +static void *sha384_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); + + if( ctx != NULL ) + mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); + + return( ctx ); +} + +static void sha384_ctx_free( void *ctx ) +{ + mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha384_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, + (const mbedtls_sha512_context *) src ); +} + +static int sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha384_info = { + MBEDTLS_MD_SHA384, + "SHA384", + 48, + 128, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +static int sha512_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) ); +} + +static int sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); +} + +const mbedtls_md_info_t mbedtls_sha512_info = { + MBEDTLS_MD_SHA512, + "SHA512", + 64, + 128, + sha512_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha512_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +#endif /* MBEDTLS_SHA512_C */ + +#endif /* MBEDTLS_MD_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/memory_buffer_alloc.c ************/ + +/* + * Buffer-based memory allocator + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ + + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + int verify; +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t alloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(MBEDTLS_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + size_t i; +#endif + + mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " + "ALLOC(%zu), SIZE(%10zu)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + mbedtls_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); + mbedtls_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain( void ) +{ + memory_header *cur = heap.first; + + mbedtls_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + mbedtls_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain( void ) +{ + memory_header *prv = heap.first, *cur; + + if( prv == NULL || verify_header( prv ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + cur = heap.first->next; + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_calloc( size_t n, size_t size ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; + void *ret; + size_t original_len, len; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + original_len = len = n * size; + + if( n == 0 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return( NULL ); + + if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.alloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p >= heap.buf + heap.len ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " + "space\n" ); +#endif + mbedtls_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + mbedtls_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + free( hdr->trace ); + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + if( heap.first_free != NULL ) + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); +} + +void mbedtls_memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int mbedtls_memory_buffer_alloc_verify( void ) +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status( void ) +{ + mbedtls_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.alloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + else + { + mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) +{ + *max_used = heap.maximum_used; + *max_blocks = heap.maximum_header_count; +} + +void mbedtls_memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_THREADING_C) +static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) +{ + void *buf; + if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) + return( NULL ); + buf = buffer_alloc_calloc( n, size ); + if( mbedtls_mutex_unlock( &heap.mutex ) ) + return( NULL ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + /* We have to good option here, but corrupting the heap seems + * worse than loosing memory. */ + if( mbedtls_mutex_lock( &heap.mutex ) ) + return; + buffer_alloc_free( ptr ); + (void) mbedtls_mutex_unlock( &heap.mutex ); +} +#endif /* MBEDTLS_THREADING_C */ + +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &heap.mutex ); + mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, + buffer_alloc_free_mutexed ); +#else + mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); +#endif + + if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + memset( buf, 0, len ); + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *)buf; + heap.first->size = len - sizeof( memory_header ); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; +} + +void mbedtls_memory_buffer_alloc_free( void ) +{ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &heap.mutex ); +#endif + mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(MBEDTLS_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( void ) +{ + if( +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used != 0 || +#endif + heap.first != heap.first_free || + (void *) heap.first != (void *) heap.buf ) + { + return( -1 ); + } + + return( 0 ); +} + +#define TEST_ASSERT( condition ) \ + if( ! (condition) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int mbedtls_memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #2 (buf not aligned): " ); + + mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #3 (full): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( p ); + + p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( q ); + + TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); + + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/net_sockets.c ************/ + +/* + * TCP/IP or UDP/IP networking functions + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_NET_C) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#endif + + + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#include + +#include +#include + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int err = errno; + + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; + return( 0 ); + } + + switch( errno = err ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret; + int type; + + struct sockaddr_storage client_addr; + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { + struct sockaddr_storage local_addr; + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_storage ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/oid.c ************/ + +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_OID_C) + + + + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ +static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ +{ \ + const TYPE_T *p = LIST; \ + const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + *ATTR2 = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_X509_EXT_NS_CERT_TYPE, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%d", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/padlock.c ************/ + +/* + * VIA PadLock support functions + * + * 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 implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PADLOCK_C) + + + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86) + +/* + * PadLock detection routine + */ +int mbedtls_padlock_has_support( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb unsupported \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "unsupported: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "memory", "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "memory", "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86 */ + +#endif /* MBEDTLS_PADLOCK_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pem.c ************/ + +/* + * Privacy Enhanced Mail (PEM) decoding + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + + + + + + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as heurisitic to try detecting password mismatchs. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if( ctx->buf != NULL ) + mbedtls_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + mbedtls_free( ctx->info ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pk.c ************/ + +/* + * Public Key abstraction layer + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PK_C) + + + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif + +#include +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return; + + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* null or NONE context can't do anything */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + if( pub == NULL || pub->pk_info == NULL || + prv == NULL || prv->pk_info == NULL || + prv->pk_info->check_pair_func == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* MBEDTLS_PK_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pk_wrap.c ************/ + +/* + * Public Key abstraction layer: wrapper functions + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PK_C) + + +/* Even if RSA not activated, for the sake of RSA-alt */ + + +#include + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#else + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#endif /* MBEDTLS_PK_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkcs11.c ************/ + +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * 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) + */ + + + +#if defined(MBEDTLS_PKCS11_C) + + + + + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); +} + +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = mbedtls_calloc( 1, cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + mbedtls_free( cert_blob ); + + return( ret ); +} + + +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + mbedtls_x509_crt cert; + + mbedtls_x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = mbedtls_pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + mbedtls_x509_crt_free( &cert ); + + return( ret ); +} + +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(MBEDTLS_PKCS11_C) */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkcs12.c ************/ + +/* + * PKCS#12 Personal Information Exchange Syntax + * + * 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) + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PKCS12_C) + + + + + +#include + +#if defined(MBEDTLS_ARC4_C) + +#endif + +#if defined(MBEDTLS_DES_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(MBEDTLS_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret; + unsigned char key[16]; + mbedtls_arc4_context ctx; + ((void) mode); + + mbedtls_arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + mbedtls_arc4_setup( &ctx, key, 16 ); + if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_arc4_free( &ctx ); + + return( ret ); +#endif /* MBEDTLS_ARC4_C */ +} + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + salt_block[i - 1] = j & 0xFF; + } + + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + pwd_block[i - 1] = j & 0xFF; + } + } + + ret = 0; + +exit: + mbedtls_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkcs5.c ************/ + +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * 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) + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PKCS5_C) + + + + + + +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif + +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret, j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + return( ret ); + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + return( ret ); + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], + slen[i], it_cnt[i], key_len[i], key ); + if( ret != 0 || + memcmp( result_key[i], key, key_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkparse.c ************/ + +/* + * Public Key layer for parsing key files and structures + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PK_PARSE_C) + + + + + +#include + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif +#if defined(MBEDTLS_PKCS5_C) + +#endif +#if defined(MBEDTLS_PKCS12_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_FS_IO) || \ + defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret; + + if ( end - *p < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, p, len ) ) != 0 ) + goto cleanup; + p += len; + + /* Import D */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + p, len, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import P */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import Q */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Complete the RSA private key */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) + goto cleanup; + + /* Check optional parameters */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; + + if( p != end ) + { + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const mbedtls_pk_info_t *pk_info; + +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) ret); + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; + + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + key, keylen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + else + { + return( 0 ); + } + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + else + { + return( 0 ); + } + +#endif /* MBEDTLS_ECP_C */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/pkwrite.c ************/ + +/* + * Public Key layer for writing key files and structures + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PK_WRITE_C) + + + + + +#include + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif +#if defined(MBEDTLS_PEM_WRITE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c = buf + size; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey: write as MPI then fix tag */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); + *c = MBEDTLS_ASN1_OCTET_STRING; + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 +#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES +#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES + +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/platform.c ************/ + +/* + * Platform abstraction layer + * + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + + + +#if defined(MBEDTLS_ENTROPY_NV_SEED) && \ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc = calloc_func; + mbedtls_free = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY */ + +#if defined(_WIN32) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret; + va_list argp; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + + va_start( argp, fmt ); +#if defined(_TRUNCATE) && !defined(__MINGW32__) + ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); +#else + ret = _vsnprintf( s, n, fmt, argp ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ripemd160.c ************/ + +/* + * RIPE MD-160 implementation + * + * 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) + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( x ^ y ^ z ) +#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) +#define F3( x, y, z ) ( ( x | ~y ) ^ z ) +#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) +#define F5( x, y, z ) ( x ^ ( y | ~z ) ) + +#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + a += f( b, c, d ) + X[r] + k; \ + a = S( a, s ) + e; \ + c = S( c, 10 ); + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + P( a, b, c, d, e, r, s, F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/rsa.c ************/ + +/* + * The RSA public-key cryptosystem + * + * 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) + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_RSA_C) + + + + + +#include + +#if defined(MBEDTLS_PKCS1_V21) + +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* constant-time buffer comparison */ +static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret; + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + + const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + const int n_missing = have_P && have_Q && have_D && have_E; + const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + const int d_missing = have_P && have_Q && !have_D && have_E; + const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + const int is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + + /* Check if key is private or public */ + const int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret; + + /* Check if key is private or public */ + int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret; + + /* Check if key is private or public */ + int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) +{ + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret; + mbedtls_mpi H, G; + + if( f_rng == NULL || nbits < 128 || exponent < 3 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( nbits % 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + + /* + * find primes P and Q with Q < P so that: + * GCD( E, (P-1)*(Q-1) ) == 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, + f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, + f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + continue; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) + continue; + + if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + } + while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + + /* + * D = E^-1 mod ((P-1)*(Q-1)) + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &H ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mbedtls_mpi T; + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + // We don't check p_rng because it won't be dereferenced here + if( f_rng == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + int ret; + size_t ilen, pad_count = 0, i; + unsigned char *p, bad, pad_done = 0; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + p = buf; + bad = 0; + + /* + * Check and get padding len in "constant-time" + */ + bad |= *p++; /* First byte must be 0 */ + + /* This test does not depend on secret data */ + if( mode == MBEDTLS_RSA_PRIVATE ) + { + bad |= *p++ ^ MBEDTLS_RSA_CRYPT; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + else + { + bad |= *p++ ^ MBEDTLS_RSA_SIGN; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ( p[i] != 0xFF ); + pad_count += ( pad_done == 0 ); + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + + bad |= ( pad_count < 8 ); + + if( bad ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + mbedtls_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret; + unsigned char *sig_try = NULL, *verif = NULL; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + const size_t sig_len = ctx->len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret; + + dst->ver = src->ver; + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + + + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/rsa_internal.c ************/ + +/* + * Helper functions for the RSA module + * + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_RSA_C) + + + + + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/sha1.c ************/ + +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * 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) + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SHA1_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA1_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ + W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/sha256.c ************/ + +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * 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) + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SHA256_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA256_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( W[i], data, 4 * i ); + else + R( i ); + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char sha256_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + int ret; + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + + } + else + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; + + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/sha512.c ************/ + +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * 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) + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SHA512_C) + + + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA512_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +#define K KK +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + +#define SHR(x,n) (x >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + i = 0; + + do + { + P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; + P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; + P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; + P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; + P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; + P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; + P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; + P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + unsigned int left; + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char sha512_padding[128] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret; + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, msglen, 0 ); + PUT_UINT64_BE( low, msglen, 8 ); + + last = (size_t)( ctx->total[0] & 0x7F ); + padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + + if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) + return( ret ); + + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if( ctx->is384 == 0 ) + { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret; + mbedtls_sha512_context ctx; + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[6][64] = +{ + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_cache.c ************/ + +/* + * SSL session cache implementation + * + * 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) + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->id_len != entry->session.id_len ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.id_len ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + + session->verify_result = entry->session.verify_result; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + if( ( session->peer_cert = mbedtls_calloc( 1, + sizeof(mbedtls_x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + mbedtls_x509_crt_init( session->peer_cert ); + if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + goto exit; + } + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; + mbedtls_ssl_cache_entry *old = NULL; +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(MBEDTLS_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(MBEDTLS_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* MBEDTLS_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* MBEDTLS_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + } + + memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + mbedtls_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); + } + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, session->peer_cert->raw.p, + session->peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + cur->session.peer_cert = NULL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_ssl_session_free( &prv->session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_free( prv->peer_cert.p ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif + cache->chain = NULL; +} + +#endif /* MBEDTLS_SSL_CACHE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_ciphersuites.c ************/ + +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#endif + + + + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except rc4, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* All AES-256 ephemeral suites */ + 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_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + 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_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + 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, + + /* All AES-128 ephemeral suites */ + 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_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + 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_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + 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, + + /* All remaining >= 128-bit ephemeral suites */ + 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, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + 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_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_AES_256_CCM_8, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + 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_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_DHE_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + 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_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + 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_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All remaining >= 128-bit suites */ + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + + /* The RSA PSK suites */ + 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, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + 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_256_CCM_8, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + 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_AES_128_CCM_8, + + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + 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_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + 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_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + 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, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) +#else + if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) +#endif + *(q++) = *p; + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_cli.c ************/ + +/* + * SSLv3/TLSv1 client-side functions + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + if( end < p || (size_t)( end - p ) < hostname_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + * + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static void cli_ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + + if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t sig_alg_len = 0; + const int *md; +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + } + + if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *grp_id; +#else + ((void) ssl); +#endif + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) +#else + for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif + { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); +#endif + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); + return; + } + + elliptic_curve_len += 2; + } + + if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + elliptic_curve_len = 0; + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) +#else + for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif + { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); +#endif + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + if( elliptic_curve_len == 0 ) + return; + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; +} + +static void cli_ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); + + if( end < p || (size_t)( end - p ) < 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + /* + * We may need to send ClientHello multiple times for Hello verification. + * We don't want to compute fresh values every time (both for performance + * and consistency reasons), so cache the extension content. + */ + if( ssl->handshake->ecjpake_cache == NULL || + ssl->handshake->ecjpake_cache_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return; + } + + memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); + ssl->handshake->ecjpake_cache_len = kkpp_len; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); + + kkpp_len = ssl->handshake->ecjpake_cache_len; + + if( (size_t)( end - p - 2 ) < kkpp_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void cli_ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + + if( end < p || (size_t)( end - p ) < 5 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->conf->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void cli_ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void cli_ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " + "extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void cli_ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " + "extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void cli_ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 + tlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( tlen ) & 0xFF ); + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static void cli_ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; + + if( end < p || (size_t)( end - p ) < 6 + alpnlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + *p = (unsigned char)( strlen( *cur ) & 0xFF ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Generate random bytes for ClientHello + */ +static int ssl_generate_random( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->handshake->randbytes; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + + /* + * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie != NULL ) + { + return( 0 ); + } +#endif + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n, olen, ext_len = 0; + unsigned char *buf; + unsigned char *p, *q; + unsigned char offer_compress; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + } + + if( ssl->conf->max_major_ver == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, " + "consider using mbedtls_ssl_config_defaults()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ( ret = ssl_generate_random( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); + return( ret ); + } + + memcpy( p, ssl->handshake->randbytes, 32 ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); + p += 32; + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTSL only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + n = ssl->session_negotiate->id_len; + + if( n < 16 || n > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->id_len = n = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + + *p++ = ssl->handshake->verify_cookie_len; + memcpy( p, ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + p += ssl->handshake->verify_cookie_len; + } + } +#endif + + /* + * Ciphersuite list + */ + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + + /* Skip writing ciphersuite length for now */ + n = 0; + q = p; + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ciphersuite_info == NULL ) + continue; + + if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || + ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) + continue; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + continue; +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + continue; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + continue; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", + ciphersuites[i] ) ); + + n++; + *p++ = (unsigned char)( ciphersuites[i] >> 8 ); + *p++ = (unsigned char)( ciphersuites[i] ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); + n++; + } + + /* Some versions of OpenSSL don't handle it correctly if not at end */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); + n++; + } +#endif + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + offer_compress = 1; +#else + offer_compress = 0; +#endif + + /* + * We don't support compression with DTLS right now: is many records come + * in the same datagram, uncompressing one could overwrite the next one. + * We don't want to add complexity for handling that case unless there is + * an actual need for it. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + offer_compress = 0; +#endif + + if( offer_compress ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) ); + + *p++ = 2; + *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", + MBEDTLS_SSL_COMPRESS_NULL ) ); + + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + + // First write extensions, then the total length + // +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + cli_ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + + cli_ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + cli_ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + cli_ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + cli_ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + cli_ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + cli_ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + cli_ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", + ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int cli_ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ssl_safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int cli_ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int cli_ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int cli_ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int cli_ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int cli_ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +static int cli_ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + name_len = buf[2]; + if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_ZLIB_SUPPORT) + int accept_comp; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + buf = ssl->in_msg; + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + + ssl->keep_current_message = 1; + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " + " min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (uint32_t) buf[2] << 24 ) | + ( (uint32_t) buf[3] << 16 ) | + ( (uint32_t) buf[4] << 8 ) | + ( (uint32_t) buf[5] ) ) ); + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + accept_comp = 0; + else +#endif + accept_comp = 1; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL && + ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) +#else /* MBEDTLS_ZLIB_SUPPORT */ + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) +#endif/* MBEDTLS_ZLIB_SUPPORT */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + + if( ssl->transform_negotiate->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); + + suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( suite_info == NULL +#if defined(MBEDTLS_ARC4_C) + || ( ssl->conf->arc4_disabled && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + if( comp != MBEDTLS_SSL_COMPRESS_NULL +#if defined(MBEDTLS_ZLIB_SUPPORT) + && comp != MBEDTLS_SSL_COMPRESS_DEFLATE +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = cli_ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); + + if( ( ret = cli_ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = cli_ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = cli_ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); + + if( ( ret = cli_ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = cli_ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); + + if( ( ret = ssl_parse_ecjpake_kkpp( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = cli_ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", + ssl->handshake->dhm_ctx.len * 8, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + + curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + if( (*p) > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " + "(psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( (*p) > end - len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " + "(psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " + "HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " + "SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered", + *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int cli_ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ecp_keypair *peer_key; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk ); + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + MBEDTLS_ECDH_THEIRS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + unsigned char *p = NULL, *end = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = cli_ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "cli_ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must " + "not be skipped" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t sig_len, hashlen; + unsigned char hash[64]; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( p != end - sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, + params_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Info from md_alg will be used instead */ + hashlen = 0; + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params, + params_len, md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Verify signature + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len ) ) != 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + size_t i; + + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" + ",%d", sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ + +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + n = ssl->handshake->dhm_ctx.len; + + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + i = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + i = 4; + n = ssl->conf->psk_identity_len; + + if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " + "SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); + i += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + n = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + n = ssl->handshake->dhm_ctx.len; + + if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" + " or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + i = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = i + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + unsigned int hashlen; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make an RSA signature of the handshake digests + */ + ssl->handshake->calc_verify( ssl, hash ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + hashlen = 36; + md_alg = MBEDTLS_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and SHA224 + * in order to satisfy 'weird' needs from the server side. + */ + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); + ssl->out_msg[5 + offset] = (unsigned char)( n ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + mbedtls_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } +#endif + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_cookie.c ************/ + +/* + * DTLS cookie callbacks implementation + * + * 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) + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( (size_t)( end - *p ) < COOKIE_LEN ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + (*p)[0] = (unsigned char)( t >> 24 ); + (*p)[1] = (unsigned char)( t >> 16 ); + (*p)[2] = (unsigned char)( t >> 8 ); + (*p)[3] = (unsigned char)( t ); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + if( ret != 0 ) + return( ret ); + + if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + return( -1 ); + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + return( -1 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_srv.c ************/ + +/* + * SSLv3/TLSv1 server-side functions + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + + +#include + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 0 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + + const unsigned char *p; + const unsigned char *end = buf + len; + + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. + * + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. + */ + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %d and hash %d", + sig_cur, md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %d not supported", md_cur ) ); + } + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Use our order of preference + */ + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_pk_type_t sig_type; +#endif + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %d", sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || + buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) + ? buf[4] : ssl->conf->max_minor_ver; + + if( ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) +#endif + if( ( buf[0] & 0x80 ) != 0 ) + return( ssl_parse_client_hello_v2( ssl ) ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message seqence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + /* We don't support fragmentation of ClientHello (yet?) */ + if( buf[1] != 0 || + msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%d (expected %d)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions ommitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + /* This may be an attacker's probe, so don't send an alert */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#if defined(MBEDTLS_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + + /* Do not parse the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + + sig_hash_alg_ext_present = 1; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%d - should not happen", sig_alg ) ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && +#endif + ssl->session_negotiate->id_len != 0 && + ssl->conf->f_get_cache != NULL && + ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + } + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* Do not write the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_record( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + size_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + + total_dn_size = 0; + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + while( crt != NULL && crt->version != 0 ) + { + dn_size = crt->subject_raw.len; + + if( end < p || + (size_t)( end - p ) < dn_size || + (size_t)( end - p ) < 2 + dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); + ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); + + ret = mbedtls_ssl_write_record( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t n = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) + unsigned char *p = ssl->out_msg + 4; + size_t len; +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + unsigned char *dig_signed = p; + size_t dig_signed_len = 0; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + + /* + * + * Part 1: Extract static ECDH parameters and abort + * if ServerKeyExchange not needed. + * + */ + + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */ + + /* + * + * Part 2: Provide key exchange parameters for chosen ciphersuite. + * + */ + + /* + * - ECJPAKE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + p += len; + n += len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + *(p++) = 0x00; + *(p++) = 0x00; + + n += 2; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) + { + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = p; + dig_signed_len = len; +#endif + + p += len; + n += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ + + /* + * - ECDHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const mbedtls_ecp_group_id *gid; + + /* Match our preference list against the offered curves */ + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, + p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = p; + dig_signed_len = len; +#endif + + p += len; + n += len; + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ + + /* + * + * Part 3: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t signature_len = 0; + unsigned int hashlen = 0; + unsigned char hash[64]; + + /* + * 3.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 + * (RFC 4492, Sec. 5.4) + * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) + */ + + mbedtls_md_type_t md_alg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* A: For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + /* B: Default hash SHA1 */ + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + { + /* C: MD5 + SHA1 */ + md_alg = MBEDTLS_MD_NONE; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); + + /* + * 3.2: Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, + dig_signed, + dig_signed_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Info from md_alg will be used instead */ + hashlen = 0; + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + + /* + * 3.3: Compute and add the signature + */ + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + *(p++) = mbedtls_ssl_hash_from_md_alg( md_alg ); + *(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg ); + + n += 2; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, + p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( signature_len >> 8 ); + *(p++) = (unsigned char)( signature_len ); + n += 2; + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); + + n += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + /* Done with actual work; add header and send. */ + + ssl->out_msglen = 4 + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + + return( 0 ); +} + +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * Also, avoid data-dependant branches here to protect against + * timing-based variants. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, + peer_pms, &peer_pmslen, + sizeof( peer_pms ), + ssl->conf->f_rng, ssl->conf->p_rng ); + + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + size_t n; + + if( ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( end - *p < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n < 1 || n > 65535 || n > (size_t) ( end - *p ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + /* Read the message without adding it to the checksum */ + do { + + if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = MBEDTLS_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* Calculate hash and verify signature */ + ssl->handshake->calc_verify( ssl, hash ); + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; + ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; + ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; + ssl->out_msg[7] = ( lifetime ) & 0xFF; + + ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); + + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_ticket.c ************/ + +/* + * TLS server tickets callbacks implementation + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +#include + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Initialze context + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +#define MAX_KEY_BYTES 32 /* 256 bits */ + +/* + * Generate/update a key + */ +static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, + unsigned char index ) +{ + int ret; + unsigned char buf[MAX_KEY_BYTES]; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = (uint32_t) mbedtls_time( NULL ); +#endif + + if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) + return( ret ); + + if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) + return( ret ); + + /* With GCM and CCM, same context can encrypt & decrypt */ + ret = mbedtls_cipher_setkey( &key->ctx, buf, + mbedtls_cipher_get_key_bitlen( &key->ctx ), + MBEDTLS_ENCRYPT ); + + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Rotate/generate keys if necessary + */ +static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) +{ +#if !defined(MBEDTLS_HAVE_TIME) + ((void) ctx); +#else + if( ctx->ticket_lifetime != 0 ) + { + uint32_t current_time = (uint32_t) mbedtls_time( NULL ); + uint32_t key_time = ctx->keys[ctx->active].generation_time; + + if( current_time > key_time && + current_time - key_time < ctx->ticket_lifetime ) + { + return( 0 ); + } + + ctx->active = 1 - ctx->active; + + return( ssl_ticket_gen_key( ctx, ctx->active ) ); + } + else +#endif /* MBEDTLS_HAVE_TIME */ + return( 0 ); +} + +/* + * Setup context for actual use + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + + cipher_info = mbedtls_cipher_info_from_type( cipher); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cipher_info->mode != MBEDTLS_MODE_GCM && + cipher_info->mode != MBEDTLS_MODE_CCM ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || + ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || + ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Serialize a session in the following format: + * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) + * n . n+2 peer_cert length = m (0 if no certificate) + * n+3 . n+2+m peer cert ASN.1 + */ +static int ssl_save_session( const mbedtls_ssl_session *session, + unsigned char *buf, size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t left = buf_len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( left < sizeof( mbedtls_ssl_session ) ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + memcpy( p, session, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + left -= sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + if( left < 3 + cert_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); + *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); + *p++ = (unsigned char)( cert_len & 0xFF ); + + if( session->peer_cert != NULL ) + memcpy( p, session->peer_cert->raw.p, cert_len ); + + p += cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + *olen = p - buf; + + return( 0 ); +} + +/* + * Unserialise session, see ssl_save_session() + */ +static int ssl_load_session( mbedtls_ssl_session *session, + const unsigned char *buf, size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( p + sizeof( mbedtls_ssl_session ) > end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( session, p, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( p + 3 > end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len == 0 ) + { + session->peer_cert = NULL; + } + else + { + int ret; + + if( p + cert_len > end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Create session ticket, with the following structure: + * + * struct { + * opaque key_name[4]; + * opaque iv[12]; + * opaque encrypted_state<0..2^16-1>; + * opaque tag[16]; + * } ticket; + * + * The key_name, iv, and length of encrypted_state are the additional + * authenticated data. + */ +int mbedtls_ssl_ticket_write( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *ticket_lifetime ) +{ + int ret; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = start; + unsigned char *iv = start + 4; + unsigned char *state_len_bytes = iv + 12; + unsigned char *state = state_len_bytes + 2; + unsigned char *tag; + size_t clear_len, ciph_len; + + *tlen = 0; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, + * in addition to session itself, that will be checked when writing it. */ + if( end - start < 4 + 12 + 2 + 16 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + key = &ctx->keys[ctx->active]; + + *ticket_lifetime = ctx->ticket_lifetime; + + memcpy( key_name, key->name, 4 ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) + goto cleanup; + + /* Dump session state */ + if( ( ret = ssl_save_session( session, + state, end - state, &clear_len ) ) != 0 || + (unsigned long) clear_len > 65535 ) + { + goto cleanup; + } + state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; + state_len_bytes[1] = ( clear_len ) & 0xff; + + /* Encrypt and authenticate */ + tag = state + clear_len; + if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, + iv, 12, key_name, 4 + 12 + 2, + state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = 4 + 12 + 2 + 16 + ciph_len; + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Select key based on name + */ +static mbedtls_ssl_ticket_key *ssl_ticket_select_key( + mbedtls_ssl_ticket_context *ctx, + const unsigned char name[4] ) +{ + unsigned char i; + + for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) + if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) + return( &ctx->keys[i] ); + + return( NULL ); +} + +/* + * Load session ticket (see mbedtls_ssl_ticket_write for structure) + */ +int mbedtls_ssl_ticket_parse( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = buf; + unsigned char *iv = buf + 4; + unsigned char *enc_len_p = iv + 12; + unsigned char *ticket = enc_len_p + 2; + unsigned char *tag; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* See mbedtls_ssl_ticket_write() */ + if( len < 4 + 12 + 2 + 16 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + tag = ticket + enc_len; + + if( len != 4 + 12 + 2 + enc_len + 16 ) + { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto cleanup; + } + + /* Select key */ + if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) + { + /* We can't know for sure but this is a likely option unless we're + * under attack - this is only informative anyway */ + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + + /* Decrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, + key_name, 4 + 12 + 2, ticket, enc_len, + ticket, &clear_len, tag, 16 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + + goto cleanup; + } + if( clear_len != enc_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + /* Actually load session */ + if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) + goto cleanup; + +#if defined(MBEDTLS_HAVE_TIME) + { + /* Check for expiration */ + mbedtls_time_t current_time = mbedtls_time( NULL ); + + if( current_time < session->start || + (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) + { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + } +#endif + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free context + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) +{ + mbedtls_cipher_free( &ctx->keys[0].ctx ); + mbedtls_cipher_free( &ctx->keys[1].ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); +} + +#endif /* MBEDTLS_SSL_TICKET_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/ssl_tls.c ************/ + +/* + * SSLv3/TLSv1 shared functions + * + * 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) + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + + + +#include + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* Length of the "epoch" field in the record header */ +static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +static int ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = +{ + MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ + 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ + 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ + 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ + 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ +}; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_CLI_C) +static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( src->peer_cert != NULL ) + { + int ret; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* + * Key material generation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + int ret = 0; + size_t i; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padding, sizeof( padding ) ); + mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char tmp[128]; + unsigned char h_i[20]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S1, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S2, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char tmp[128]; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += md_len ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + unsigned char tmp[64]; + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t mac_key_len; + size_t iv_copy_len; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + + mbedtls_ssl_session *session = ssl->session_negotiate; + mbedtls_ssl_transform *transform = ssl->transform_negotiate; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + transform->ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", + transform->ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * SSLv3: + * master = + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) + * + * TLSv1+: + * master = PRF( premaster, "master secret", randbytes )[0..47] + */ + if( handshake->resume == 0 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + unsigned char session_hash[48]; + size_t hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + + ssl->handshake->calc_verify( ssl, session_hash ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { +#if defined(MBEDTLS_SHA512_C) + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + hash_len = 48; + } + else +#endif + hash_len = 32; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + hash_len = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); + + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "extended master secret", + session_hash, hash_len, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + } + else +#endif + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + } + else + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + + /* + * Swap the client and server random values. + */ + memcpy( tmp, handshake->randbytes, 64 ); + memcpy( handshake->randbytes, tmp + 32, 32 ); + memcpy( handshake->randbytes + 32, tmp, 32 ); + mbedtls_zeroize( tmp, sizeof( tmp ) ); + + /* + * SSLv3: + * key block = + * MD5( master + SHA1( 'A' + master + randbytes ) ) + + * MD5( master + SHA1( 'BB' + master + randbytes ) ) + + * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + + * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + + * ... + * + * TLSv1: + * key block = PRF( master, "key expansion", randbytes ) + */ + ret = handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + transform->keylen = cipher_info->key_bitlen / 8; + + if( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->mode == MBEDTLS_MODE_CCM ) + { + transform->maclen = 0; + mac_key_len = 0; + + transform->ivlen = 12; + transform->fixed_ivlen = 4; + + /* Minimum length is expicit IV + tag */ + transform->minlen = transform->ivlen - transform->fixed_ivlen + + ( transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + } + else + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + return( ret ); + } + + /* Get MAC length */ + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + { + transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + /* Fall back to old, non-compliant version of the truncated + * HMAC implementation which also truncates the key + * (Mbed TLS versions from 1.3 to 2.6.0) */ + mac_key_len = transform->maclen; +#endif + } +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV except for SSL3 and TLS 1.0 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", + transform->keylen, transform->minlen, transform->ivlen, + transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + transform->keylen; + + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + mac_key_len * 2 + transform->keylen; + key2 = keyblk + mac_key_len * 2; + + mac_enc = keyblk + mac_key_len; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( mac_key_len > sizeof transform->mac_enc ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, mac_key_len ); + memcpy( transform->mac_dec, mac_dec, mac_key_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_init != NULL ) + { + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); + + if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + mac_key_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( ssl->conf->f_export_keys != NULL ) + { + ssl->conf->f_export_keys( ssl->conf->p_export_keys, + session->master, keyblk, + mac_key_len, transform->keylen, + iv_copy_len ); + } +#endif + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( cipher_info->mode == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + mbedtls_zeroize( keyblk, sizeof( keyblk ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + // Initialize compression + // + if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_1, 48 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_2, 48 ); + mbedtls_md5_update_ret( &md5, hash, 16 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); + mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + mbedtls_md5_finish_ret( &md5, hash ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) +{ + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish_ret( &sha256, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); + + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) +{ + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish_ret( &sha512, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); + + return; +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = ssl->conf->psk; + size_t psk_len = ssl->conf->psk_len; + + /* If the psk callback was called, use its result */ + if( ssl->handshake->psk != NULL ) + { + psk = ssl->handshake->psk; + psk_len = ssl->handshake->psk_len; + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +/* + * SSLv3.0 MAC functions + */ +#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL_MAC_MAX_BYTES] ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, header, 11 ); + mbedtls_md_update( md_ctx, buf, len ); + mbedtls_md_finish( md_ctx, out ); + + memset( padding, 0x5C, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, out, md_size ); + mbedtls_md_finish( md_ctx, out ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) +#define SSL_SOME_MODES_USE_MAC +#endif + +/* + * Encryption/decryption functions + */ +static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( ssl->session_out == NULL || ssl->transform_out == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", + (unsigned) ssl->out_msglen, + MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Add MAC before if needed + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + unsigned char mac[SSL_MAC_MAX_BYTES]; + + ssl_mac( &ssl->transform_out->md_ctx_enc, + ssl->transform_out->mac_enc, + ssl->out_msg, ssl->out_msglen, + ssl->out_ctr, ssl->out_msgtype, + mac ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_msg, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", + ssl->out_msg + ssl->out_msglen, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* AEAD not the only option */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + ssl->out_msg, ssl->out_msglen, + ssl->out_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM ) + { + int ret; + size_t enc_msglen, olen; + unsigned char *enc_msg; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + /* + * Generate IV + */ + if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + /* + * Encrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + add_data, 13, + enc_msg, enc_msglen, + enc_msg, &olen, + enc_msg + enc_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + + if( olen != enc_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen += taglen; + auth_done++; + + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret; + unsigned char *enc_msg; + size_t enc_msglen, padlen, olen = 0, i; + + padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % + ssl->transform_out->ivlen; + if( padlen == ssl->transform_out->ivlen ) + padlen = 0; + + for( i = 0; i <= padlen; i++ ) + ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; + + ssl->out_msglen += padlen + 1; + + enc_msglen = ssl->out_msglen; + enc_msg = ssl->out_msg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( ssl->out_iv, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + ssl->out_msglen, ssl->transform_out->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + enc_msg, enc_msglen, + enc_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( enc_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); + } +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_iv, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_iv + ssl->out_msglen ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) +{ + size_t i; + mbedtls_cipher_mode_t mode; + int auth_done = 0; +#if defined(SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + + if( ssl->session_in == NULL || ssl->transform_in == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); + + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", + ssl->in_msglen, ssl->transform_in->minlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + padlen = 0; + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + ssl->in_msg, ssl->in_msglen, + ssl->in_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM ) + { + int ret; + size_t dec_msglen, olen; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_iv_len = ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen; + + if( ssl->in_msglen < explicit_iv_len + taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", ssl->in_msglen, + explicit_iv_len, taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; + + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + ssl->in_msglen = dec_msglen; + + memcpy( add_data, ssl->in_ctr, 8 ); + add_data[8] = ssl->in_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, + ssl->in_iv, + ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + add_data, 13, + dec_msg, dec_msglen, + dec_msg_result, &olen, + dec_msg + dec_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + if( olen != dec_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + /* + * Decrypt and check the padding + */ + int ret; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + size_t dec_msglen; + size_t minlen = 0; + size_t olen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + minlen += ssl->transform_in->ivlen; +#endif + + if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || + ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", ssl->in_msglen, + ssl->transform_in->ivlen, + ssl->transform_in->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + dec_msglen = ssl->in_msglen; + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + dec_msglen -= ssl->transform_in->maclen; + ssl->in_msglen -= ssl->transform_in->maclen; + + memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, + ssl->in_iv, ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, + ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect, + ssl->transform_in->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + ssl->in_msglen, ssl->transform_in->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + dec_msglen -= ssl->transform_in->ivlen; + ssl->in_msglen -= ssl->transform_in->ivlen; + + for( i = 0; i < ssl->transform_in->ivlen; i++ ) + ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + dec_msg, dec_msglen, + dec_msg_result, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( dec_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); + } +#endif + + padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; + + if( ssl->in_msglen < ssl->transform_in->maclen + padlen && + auth_done == 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); +#endif + padlen = 0; + correct = 0; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( padlen > ssl->transform_in->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, ssl->transform_in->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * TLSv1+: always check the padding up to the first failure + * and fake check up to 256 bytes of padding + */ + size_t pad_count = 0, real_count = 1; + size_t padding_idx = ssl->in_msglen - padlen - 1; + + /* + * Padding is guaranteed to be incorrect if: + * 1. padlen >= ssl->in_msglen + * + * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + + * ssl->transform_in->maclen + * + * In both cases we reset padding_idx to a safe value (0) to + * prevent out-of-buffer reads. + */ + correct &= ( ssl->in_msglen >= padlen + 1 ); + correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + + ssl->transform_in->maclen ); + + padding_idx *= correct; + + for( i = 1; i <= 256; i++ ) + { + real_count &= ( i <= padlen ); + pad_count += real_count * + ( ssl->in_msg[padding_idx + i] == padlen - 1 ); + } + + correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_msglen -= padlen; + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + ssl->in_msg, ssl->in_msglen ); + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + + ssl->in_msglen -= ssl->transform_in->maclen; + + ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_in->md_ctx_dec, + ssl->transform_in->mac_dec, + ssl->in_msg, ssl->in_msglen, + ssl->in_ctr, ssl->in_msgtype, + mac_expect ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * Process MAC and always update for padlen afterwards to make + * total time independent of padlen + * + * extra_run compensates MAC check for padlen + * + * Known timing attacks: + * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) + * + * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values + * correctly. (We round down instead of up, so -56 is the correct + * value for our calculations instead of -55) + */ + size_t j, extra_run = 0; + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + + extra_run &= correct * 0xFF; + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, + ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); + /* Call mbedtls_md_process at least once due to cache attacks */ + for( j = 0; j < extra_run + 1; j++ ) + mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, + ssl->transform_in->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif /* SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ssl->in_msglen == 0 ) + { + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->out_msg; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->in_msg; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - + ssl->transform_in->ctx_inflate.avail_out; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret; + size_t len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* Just to be sure */ + if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split accross datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf, i; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + + ssl->out_msglen - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + ssl->out_left -= ret; + } + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); + memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + if( ssl->transform_out != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif +} + +/* + * Retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl_swap_epochs( ssl ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + int ret; + mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl_swap_epochs( ssl ); + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + ssl->handshake->cur_msg = cur->next; + + MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* Cancel timer */ + ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Record layer functions + */ + +/* + * Write current record. + * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0, out_msg_type; + size_t len = ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + ; /* Skip special handshake treatment when resending */ + } + else +#endif + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + out_msg_type = ssl->out_msg[0]; + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); + ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); + ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %u, maximum %u", + (unsigned) ( ssl->in_hslen - 4 ), + (unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); + ssl->out_msglen += 8; + len += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* We don't fragment, so frag_offset = 0 and frag_len = len */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + } + + /* Save handshake and CCS messages for resending */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && + ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || + ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + } + + ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], + ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Reassemble fragmented DTLS handshake messages. + * + * Use a temporary buffer for reassembly, divided in two parts: + * - the first holds the reassembled message (including handshake header), + * - the second holds a bitmask indicating which parts of the message + * (excluding headers) have been received so far. + */ +static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) +{ + unsigned char *msg, *bitmask; + size_t frag_len, frag_off; + size_t msg_len = ssl->in_hslen - 12; /* Without headers */ + + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * For first fragment, check size and allocate buffer + */ + if( ssl->handshake->hs_msg == NULL ) + { + size_t alloc_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* The bitmask needs one bit per byte of message excluding header */ + alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); + + ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); + if( ssl->handshake->hs_msg == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); + memset( ssl->handshake->hs_msg + 6, 0, 3 ); + memcpy( ssl->handshake->hs_msg + 9, + ssl->handshake->hs_msg + 1, 3 ); + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + msg = ssl->handshake->hs_msg + 12; + bitmask = msg + msg_len; + + /* + * Check and copy current fragment + */ + frag_off = ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8]; + frag_len = ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11]; + + if( frag_off + frag_len > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", + frag_off, frag_len, msg_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( frag_len + 12 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", + frag_len, ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + ssl_bitmask_set( bitmask, frag_off, frag_len ); + + /* + * Do we have the complete message by now? + * If yes, finalize it, else ask to read the next record. + */ + if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); + + if( frag_len + 12 < ssl->in_msglen ) + { + /* + * We'got more handshake messages in the same record. + * This case is not handled now because no know implementation does + * that and it's hard to test, so we prefer to fail cleanly for now. + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( ssl->in_left > ssl->next_record_offset ) + { + /* + * We've got more data in the buffer after the current record, + * that we don't want to overwrite. Move it before writing the + * reassembled message, and adjust in_left and next_record_offset. + */ + unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; + unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; + size_t remain_len = ssl->in_left - ssl->next_record_offset; + + /* First compute and check new lengths */ + ssl->next_record_offset = new_remain - ssl->in_hdr; + ssl->in_left = ssl->next_record_offset + remain_len; + + if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memmove( new_remain, cur_remain, remain_len ); + } + + memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); + + mbedtls_free( ssl->handshake->hs_msg ); + ssl->handshake->hs_msg = NULL; + + MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", + ssl->in_msg, ssl->in_hslen ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( + ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + /* ssl->handshake is NULL when receiving ClientHello for renego */ + if( ssl->handshake != NULL && + recv_msg_seq != ssl->handshake->in_msg_seq ) + { + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Reassemble if current message is fragmented or reassembly is + * already in progress */ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || + ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + + if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); + return( ret ); + } + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->handshake != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + ssl->handshake->in_msg_seq++; + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* Forward declaration */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + if( f_cookie_write == NULL || f_cookie_check == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * mbedtls_ssl_read_record() will ignore the record if anything else than + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function + * cannot not return 0. + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t len; + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); + } + + if( ret == 0 ) + { + /* Got a valid cookie, partially reset context */ + if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) +{ + int major_ver, minor_ver; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); + + ssl->in_msgtype = ssl->in_hdr[0]; + ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->in_msgtype, + major_ver, minor_ver, ssl->in_msglen ) ); + + /* Check record type */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && + ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* Silently ignore invalid DTLS records as recommended by RFC 6347 + * Section 4.1.2.7 */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check version */ + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against the size of our buffer */ + if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN + - (size_t)( ssl->in_msg - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against bounds of the current transform and version */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen < 1 || + ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif + } + + /* + * DTLS-related tests done last, because most of them may result in + * silently dropping the record (but not the whole datagram), and we only + * want to consider that after ensuring that the "basic" fields (type, + * version, length) are sane. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* Drop unexpected ChangeCipherSpec messages */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Check epoch (and sequence number) with DTLS */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + rec_epoch == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* Replay detection only works for the current epoch */ + if( rec_epoch == ssl->in_epoch && + mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +/* + * If applicable, decrypt (and decompress) record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + ssl->in_msg, ssl->in_msglen ); + + if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + return( 0 ); +} + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* + * Step A + * + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * NOTE: This needs to be fixed, since like for + * handshake messages it is allowed to have + * multiple alerts witin a single record. + * Internal reference IOTSSL-1321. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is *NOT* necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is FAULTY and should be changed at + * some point. Internal reference IOTSSL-1414. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + /* + * Step B + * + * Fetch and decode new record if current one is fully consumed. + * + */ + + if( ssl->in_msglen > 0 ) + { + /* There's something left to be processed in the current record. */ + return( 0 ); + } + + /* Need to fetch a new record */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +read_record_header: +#endif + + /* Current record either fully processed or to be discarded. */ + + if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = ssl->in_msglen + + mbedtls_ssl_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + goto read_record_header; + } +#endif + return( ret ); + } + + /* + * Read and optionally decrypt the message contents + */ + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + + if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || + ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + goto read_record_header; + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + /* + * When we sent the last flight of the handshake, we MUST respond to a + * retransmit of the peer's previous flight with a retransmit. (In + * practice, only the Finished message will make it, other messages + * including CCS use the old transform so they're dropped as invalid.) + * + * If the record we received is not a handshake message, however, it + * means the peer received our last flight so we can clean up + * handshake info. + * + * This check needs to be done before prepare_handshake() due to an edge + * case: if the client immediately requests renegotiation, this + * finishes the current handshake first, avoiding the new ClientHello + * being mistaken for an ancient message in the current handshake. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + else + { + ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +#else +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + int authmode = ssl->conf->authmode; + uint8_t alert; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; +#endif + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_SRV_C */ + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); + mbedtls_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, + sizeof( mbedtls_x509_crt ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + + i += 3; + + while( i < ssl->in_hslen ) + { + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + /* + * On client, make sure the server cert doesn't change during renego to + * avoid "triple handshake" attack: https://secure-resumption.com/ + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->session->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + if( ssl->session->peer_cert->raw.len != + ssl->session_negotiate->peer_cert->raw.len || + memcmp( ssl->session->peer_cert->raw.p, + ssl->session_negotiate->peer_cert->raw.p, + ssl->session->peer_cert->raw.len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_with_profile( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) + { + ret = 0; + } + + if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", + ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); + } + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + /* + * Set the in_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +} +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +} +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_finish_ret( &md5, md5sum ); + + mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); + mbedtls_sha1_finish_ret( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_update_ret( &md5, md5sum, 16 ); + mbedtls_md5_finish_ret( &md5, buf ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); + mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish_ret( &sha1, buf + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padbuf[36]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_md5_finish_ret( &md5, padbuf ); + mbedtls_sha1_finish_ret( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_sha256_context sha256; + unsigned char padbuf[32]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA256_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_sha256_finish_ret( &sha256, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha256_free( &sha256 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static void ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_sha512_context sha512; + unsigned char padbuf[48]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA512_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_sha512_finish_ret( &sha512, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha512_free( &sha512 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and swith in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + /* + * Set the out_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); + + /* Set sequence_number to zero */ + memset( ssl->out_ctr + 2, 0, 6 ); + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->out_ctr, 0, 8 ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define SSL_MAX_HASH_LEN 36 +#else +#define SSL_MAX_HASH_LEN 12 +#endif + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned int hash_len; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* There is currently no ciphersuite using another length with TLS 1.2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + hash_len = 36; + else +#endif + hash_len = 12; + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_init( &handshake->fin_md5 ); + mbedtls_sha1_init( &handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_init( &handshake->fin_sha256 ); + mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif +} + +static void ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl->handshake ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + ssl_set_timer( ssl, 0 ); + } +#endif + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Setup an SSL context + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret; + const size_t len = MBEDTLS_SSL_BUFFER_LEN; + + ssl->conf = conf; + + /* + * Prepare base structures + */ + if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || + ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); + mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->out_ctr = ssl->out_buf + 3; + ssl->out_len = ssl->out_buf + 11; + ssl->out_iv = ssl->out_buf + 13; + ssl->out_msg = ssl->out_buf + 13; + + ssl->in_hdr = ssl->in_buf; + ssl->in_ctr = ssl->in_buf + 3; + ssl->in_len = ssl->in_buf + 11; + ssl->in_iv = ssl->in_buf + 13; + ssl->in_msg = ssl->in_buf + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_buf; + ssl->out_hdr = ssl->out_buf + 8; + ssl->out_len = ssl->out_buf + 11; + ssl->out_iv = ssl->out_buf + 13; + ssl->out_msg = ssl->out_buf + 13; + + ssl->in_ctr = ssl->in_buf; + ssl->in_hdr = ssl->in_buf + 8; + ssl->in_len = ssl->in_buf + 11; + ssl->in_iv = ssl->in_buf + 13; + ssl->in_msg = ssl->in_buf + 13; + } + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret; + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + /* Cancel any possibly running timer */ + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + + ssl->in_msg = ssl->in_buf + 13; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + if( partial == 0 ) + ssl->in_left = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + + ssl->keep_current_message = 0; + + ssl->out_msg = ssl->out_buf + 13; + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + if( partial == 0 ) + memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_reset != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); + if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + if( partial == 0 ) + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; +} + +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ) +{ + if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return; + + if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + conf->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new; + + new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new->cert = cert; + new->key = key; + new->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + if( psk == NULL || psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* Identity len will be encoded on two bytes */ + if( ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( conf->psk != NULL ) + { + mbedtls_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } + + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || + ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) + { + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk = NULL; + conf->psk_identity = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + conf->psk_len = psk_len; + conf->psk_identity_len = psk_identity_len; + + memcpy( conf->psk, psk, conf->psk_len ); + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + return( 0 ); +} + +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ) +{ + if( psk == NULL || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->handshake->psk != NULL ) + { + mbedtls_zeroize( ssl->handshake->psk, ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } + + if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->psk_len = psk_len; + memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); + + return( 0 ); +} + +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || + ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) +{ + int ret; + + if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ) +{ + conf->sig_hashes = hashes; +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECP_C) +/* + * Set the allowed elliptic curves + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list ) +{ + conf->curve_list = curve_list; +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ + + if( hostname == NULL ) + { + ssl->hostname = NULL; + } + else + { + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->hostname, hostname, hostname_len ); + + ssl->hostname[hostname_len] = '\0'; + } + + return( 0 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) +{ + conf->fallback = fallback; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_ARC4_C) +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) +{ + conf->arc4_disabled = arc4; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) +{ + conf->trunc_hmac = truncate; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) +{ + conf->cbc_record_splitting = split; +} +#endif + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + conf->f_export_keys = f_export_keys; + conf->p_export_keys = p_export_keys; +} +#endif + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "DTLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion; + const mbedtls_ssl_transform *transform = ssl->transform_out; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + transform_expansion = transform->maclen + + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->conf->mfl_code]; + + /* + * Check if a smaller max length was negotiated + */ + if( ssl->session_out != NULL && + mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + { + max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + } + + return max_len; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return( ssl->session->peer_cert ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ssl_session_copy( dst, ssl->session ) ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} + +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* + * TODO + * + * The logic should be streamlined here: + * + * Instead of + * + * - Manually checking whether ssl->in_offt is NULL + * - Fetching a new record if yes + * - Setting ssl->in_offt if one finds an application record + * - Resetting keep_current_message after handling the application data + * + * one should + * + * - Adapt read_record to set ssl->in_offt automatically + * when a new application data record is processed. + * - Always call mbedtls_ssl_read_record here. + * + * This way, the logic of ssl_read would be much clearer: + * + * (1) Always call record layer and see what kind of record is on + * and have it ready for consumption (in particular, in_offt + * properly set for application data records). + * (2) If it's application data (either freshly fetched + * or something already being partially processed), + * serve the read request from it. + * (3) If it's something different from application data, + * handle it accordingly, e.g. potentially start a + * renegotiation. + * + * This will also remove the need to manually reset + * ssl->keep_current_message = 0 below. + * + */ + + if( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, + * taking care of max fragment length and buffer size + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); +#else + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %d > %d", + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } + + if( ssl->out_left != 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data, doing 1/n-1 splitting if necessary. + * + * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, + * then the caller will call us again with the same arguments, so + * remember whether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); + + mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) +{ + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_free( &handshake->fin_md5 ); + mbedtls_sha1_free( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + mbedtls_free( handshake->hs_msg ); + ssl_flight_free( handshake->flight ); +#endif + + mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + } +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { + mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->out_buf ); + } + + if( ssl->in_buf != NULL ) + { + mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->in_buf ); + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->compress_buf ); + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_finish != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); + mbedtls_ssl_hw_record_finish( ssl ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; +#endif + +#if defined(MBEDTLS_ECP_C) +static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { + MBEDTLS_ECP_DP_SECP256R1, + MBEDTLS_ECP_DP_SECP384R1, + MBEDTLS_ECP_DP_NONE +}; +#endif + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_ARC4_C) + conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_g ) ) ) != 0 ) + { + return( ret ); + } + } +#endif + + /* + * Preset-specific defaults + */ + switch( preset ) + { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_suiteb_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = ssl_preset_suiteb_curves; +#endif + break; + + /* + * Default + */ + default: + conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; +#endif + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = mbedtls_ecp_grp_id_list(); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_zeroize( conf->psk, conf->psk_len ); + mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk_len = 0; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_group_id *gid; + + if( ssl->conf->curve_list == NULL ) + return( -1 ); + + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ + !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + + switch( md ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ) +{ + int ret = 0; + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); + goto exit; + } + + if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, + data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, + output + 16 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); + goto exit; + } + +exit: + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); + +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + + mbedtls_md_init( &ctx ); + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_TLS_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/threading.c ************/ + +/* + * Threading abstraction layer + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_THREADING_C) + + + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; + +#endif /* MBEDTLS_THREADING_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/timing.c ************/ + +/* + * Portable interface to the CPU cycle counter + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + + + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static DWORD WINAPI TimerProc( LPVOID TimerContext ) +{ + ((void) TimerContext); + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + return( TRUE ); +} + +void mbedtls_set_alarm( int seconds ) +{ + DWORD ThreadId; + + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ + { \ + if( verbose != 0 ) \ + { \ + mbedtls_printf( "failed at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + return( 1 ); \ + } while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; + struct mbedtls_timing_hr_time hires; + uint32_t a = 0, b = 0; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + { + secs = 1; + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + FAIL; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + { + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ + + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b ); /* T = a + b + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_TIMING_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/version.c ************/ + +/* + * Version information + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_VERSION_C) + + +#include + +unsigned int mbedtls_version_get_number( void ) +{ + return( MBEDTLS_VERSION_NUMBER ); +} + +void mbedtls_version_get_string( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING, + sizeof( MBEDTLS_VERSION_STRING ) ); +} + +void mbedtls_version_get_string_full( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING_FULL, + sizeof( MBEDTLS_VERSION_STRING_FULL ) ); +} + +#endif /* MBEDTLS_VERSION_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/version_features.c ************/ + +/* + * Version feature information + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_VERSION_C) + + + +#include + +static const char *features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +#if defined(MBEDTLS_HAVE_ASM) + "MBEDTLS_HAVE_ASM", +#endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_NO_UDBL_DIVISION) + "MBEDTLS_NO_UDBL_DIVISION", +#endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_HAVE_SSE2) + "MBEDTLS_HAVE_SSE2", +#endif /* MBEDTLS_HAVE_SSE2 */ +#if defined(MBEDTLS_HAVE_TIME) + "MBEDTLS_HAVE_TIME", +#endif /* MBEDTLS_HAVE_TIME */ +#if defined(MBEDTLS_HAVE_TIME_DATE) + "MBEDTLS_HAVE_TIME_DATE", +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#if defined(MBEDTLS_PLATFORM_MEMORY) + "MBEDTLS_PLATFORM_MEMORY", +#endif /* MBEDTLS_PLATFORM_MEMORY */ +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + "MBEDTLS_PLATFORM_EXIT_ALT", +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + "MBEDTLS_PLATFORM_TIME_ALT", +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + "MBEDTLS_PLATFORM_FPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + "MBEDTLS_PLATFORM_PRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + "MBEDTLS_PLATFORM_SNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + "MBEDTLS_PLATFORM_NV_SEED_ALT", +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ +#if defined(MBEDTLS_DEPRECATED_WARNING) + "MBEDTLS_DEPRECATED_WARNING", +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#if defined(MBEDTLS_DEPRECATED_REMOVED) + "MBEDTLS_DEPRECATED_REMOVED", +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARC4_ALT) + "MBEDTLS_ARC4_ALT", +#endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_BLOWFISH_ALT) + "MBEDTLS_BLOWFISH_ALT", +#endif /* MBEDTLS_BLOWFISH_ALT */ +#if defined(MBEDTLS_CAMELLIA_ALT) + "MBEDTLS_CAMELLIA_ALT", +#endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_CCM_ALT) + "MBEDTLS_CCM_ALT", +#endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CMAC_ALT) + "MBEDTLS_CMAC_ALT", +#endif /* MBEDTLS_CMAC_ALT */ +#if defined(MBEDTLS_DES_ALT) + "MBEDTLS_DES_ALT", +#endif /* MBEDTLS_DES_ALT */ +#if defined(MBEDTLS_DHM_ALT) + "MBEDTLS_DHM_ALT", +#endif /* MBEDTLS_DHM_ALT */ +#if defined(MBEDTLS_ECJPAKE_ALT) + "MBEDTLS_ECJPAKE_ALT", +#endif /* MBEDTLS_ECJPAKE_ALT */ +#if defined(MBEDTLS_GCM_ALT) + "MBEDTLS_GCM_ALT", +#endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_MD2_ALT) + "MBEDTLS_MD2_ALT", +#endif /* MBEDTLS_MD2_ALT */ +#if defined(MBEDTLS_MD4_ALT) + "MBEDTLS_MD4_ALT", +#endif /* MBEDTLS_MD4_ALT */ +#if defined(MBEDTLS_MD5_ALT) + "MBEDTLS_MD5_ALT", +#endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_RIPEMD160_ALT) + "MBEDTLS_RIPEMD160_ALT", +#endif /* MBEDTLS_RIPEMD160_ALT */ +#if defined(MBEDTLS_RSA_ALT) + "MBEDTLS_RSA_ALT", +#endif /* MBEDTLS_RSA_ALT */ +#if defined(MBEDTLS_SHA1_ALT) + "MBEDTLS_SHA1_ALT", +#endif /* MBEDTLS_SHA1_ALT */ +#if defined(MBEDTLS_SHA256_ALT) + "MBEDTLS_SHA256_ALT", +#endif /* MBEDTLS_SHA256_ALT */ +#if defined(MBEDTLS_SHA512_ALT) + "MBEDTLS_SHA512_ALT", +#endif /* MBEDTLS_SHA512_ALT */ +#if defined(MBEDTLS_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_ALT */ +#if defined(MBEDTLS_MD2_PROCESS_ALT) + "MBEDTLS_MD2_PROCESS_ALT", +#endif /* MBEDTLS_MD2_PROCESS_ALT */ +#if defined(MBEDTLS_MD4_PROCESS_ALT) + "MBEDTLS_MD4_PROCESS_ALT", +#endif /* MBEDTLS_MD4_PROCESS_ALT */ +#if defined(MBEDTLS_MD5_PROCESS_ALT) + "MBEDTLS_MD5_PROCESS_ALT", +#endif /* MBEDTLS_MD5_PROCESS_ALT */ +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + "MBEDTLS_RIPEMD160_PROCESS_ALT", +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + "MBEDTLS_SHA1_PROCESS_ALT", +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + "MBEDTLS_SHA256_PROCESS_ALT", +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + "MBEDTLS_SHA512_PROCESS_ALT", +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ +#if defined(MBEDTLS_DES_SETKEY_ALT) + "MBEDTLS_DES_SETKEY_ALT", +#endif /* MBEDTLS_DES_SETKEY_ALT */ +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + "MBEDTLS_DES_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + "MBEDTLS_DES3_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + "MBEDTLS_AES_SETKEY_ENC_ALT", +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + "MBEDTLS_AES_SETKEY_DEC_ALT", +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + "MBEDTLS_AES_ENCRYPT_ALT", +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ +#if defined(MBEDTLS_AES_DECRYPT_ALT) + "MBEDTLS_AES_DECRYPT_ALT", +#endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + "MBEDTLS_ECDH_GEN_PUBLIC_ALT", +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + "MBEDTLS_ECDSA_VERIFY_ALT", +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + "MBEDTLS_ECDSA_SIGN_ALT", +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + "MBEDTLS_ECDSA_GENKEY_ALT", +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + "MBEDTLS_ECP_INTERNAL_ALT", +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + "MBEDTLS_ECP_ADD_MIXED_ALT", +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + "MBEDTLS_ECP_DOUBLE_JAC_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + "MBEDTLS_ENTROPY_HARDWARE_ALT", +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#if defined(MBEDTLS_AES_ROM_TABLES) + "MBEDTLS_AES_ROM_TABLES", +#endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + "MBEDTLS_CAMELLIA_SMALL_MEMORY", +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + "MBEDTLS_CIPHER_MODE_CBC", +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_CFB) + "MBEDTLS_CIPHER_MODE_CFB", +#endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_CTR) + "MBEDTLS_CIPHER_MODE_CTR", +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + "MBEDTLS_CIPHER_NULL_CIPHER", +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + "MBEDTLS_CIPHER_PADDING_PKCS7", +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + "MBEDTLS_CIPHER_PADDING_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + "MBEDTLS_ECP_DP_SECP192R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + "MBEDTLS_ECP_DP_SECP224R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + "MBEDTLS_ECP_DP_SECP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + "MBEDTLS_ECP_DP_SECP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + "MBEDTLS_ECP_DP_SECP521R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + "MBEDTLS_ECP_DP_SECP192K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + "MBEDTLS_ECP_DP_SECP224K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + "MBEDTLS_ECP_DP_SECP256K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + "MBEDTLS_ECP_DP_BP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + "MBEDTLS_ECP_DP_BP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + "MBEDTLS_ECP_DP_BP512R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + "MBEDTLS_ECP_DP_CURVE25519_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_NIST_OPTIM) + "MBEDTLS_ECP_NIST_OPTIM", +#endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + "MBEDTLS_ECDSA_DETERMINISTIC", +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + "MBEDTLS_PK_PARSE_EC_EXTENDED", +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + "MBEDTLS_ERROR_STRERROR_DUMMY", +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ +#if defined(MBEDTLS_GENPRIME) + "MBEDTLS_GENPRIME", +#endif /* MBEDTLS_GENPRIME */ +#if defined(MBEDTLS_FS_IO) + "MBEDTLS_FS_IO", +#endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + "MBEDTLS_NO_PLATFORM_ENTROPY", +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + "MBEDTLS_ENTROPY_FORCE_SHA256", +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + "MBEDTLS_ENTROPY_NV_SEED", +#endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_MEMORY_DEBUG) + "MBEDTLS_MEMORY_DEBUG", +#endif /* MBEDTLS_MEMORY_DEBUG */ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + "MBEDTLS_MEMORY_BACKTRACE", +#endif /* MBEDTLS_MEMORY_BACKTRACE */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + "MBEDTLS_PK_RSA_ALT_SUPPORT", +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ +#if defined(MBEDTLS_PKCS1_V15) + "MBEDTLS_PKCS1_V15", +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + "MBEDTLS_PKCS1_V21", +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_RSA_NO_CRT) + "MBEDTLS_RSA_NO_CRT", +#endif /* MBEDTLS_RSA_NO_CRT */ +#if defined(MBEDTLS_SELF_TEST) + "MBEDTLS_SELF_TEST", +#endif /* MBEDTLS_SELF_TEST */ +#if defined(MBEDTLS_SHA256_SMALLER) + "MBEDTLS_SHA256_SMALLER", +#endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_DEBUG_ALL) + "MBEDTLS_SSL_DEBUG_ALL", +#endif /* MBEDTLS_SSL_DEBUG_ALL */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + "MBEDTLS_SSL_ENCRYPT_THEN_MAC", +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + "MBEDTLS_SSL_FALLBACK_SCSV", +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + "MBEDTLS_SSL_HW_RECORD_ACCEL", +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + "MBEDTLS_SSL_CBC_RECORD_SPLITTING", +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + "MBEDTLS_SSL_PROTO_SSL3", +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) + "MBEDTLS_SSL_PROTO_TLS1", +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + "MBEDTLS_SSL_PROTO_TLS1_1", +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + "MBEDTLS_SSL_PROTO_TLS1_2", +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + "MBEDTLS_SSL_PROTO_DTLS", +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_ALPN) + "MBEDTLS_SSL_ALPN", +#endif /* MBEDTLS_SSL_ALPN */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + "MBEDTLS_SSL_DTLS_ANTI_REPLAY", +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + "MBEDTLS_SSL_DTLS_HELLO_VERIFY", +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + "MBEDTLS_SSL_EXPORT_KEYS", +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + "MBEDTLS_SSL_TRUNCATED_HMAC", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_THREADING_ALT) + "MBEDTLS_THREADING_ALT", +#endif /* MBEDTLS_THREADING_ALT */ +#if defined(MBEDTLS_THREADING_PTHREAD) + "MBEDTLS_THREADING_PTHREAD", +#endif /* MBEDTLS_THREADING_PTHREAD */ +#if defined(MBEDTLS_VERSION_FEATURES) + "MBEDTLS_VERSION_FEATURES", +#endif /* MBEDTLS_VERSION_FEATURES */ +#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + "MBEDTLS_X509_CHECK_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + "MBEDTLS_X509_RSASSA_PSS_SUPPORT", +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + "MBEDTLS_ZLIB_SUPPORT", +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_AESNI_C) + "MBEDTLS_AESNI_C", +#endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AES_C) + "MBEDTLS_AES_C", +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_ARC4_C) + "MBEDTLS_ARC4_C", +#endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_ASN1_PARSE_C) + "MBEDTLS_ASN1_PARSE_C", +#endif /* MBEDTLS_ASN1_PARSE_C */ +#if defined(MBEDTLS_ASN1_WRITE_C) + "MBEDTLS_ASN1_WRITE_C", +#endif /* MBEDTLS_ASN1_WRITE_C */ +#if defined(MBEDTLS_BASE64_C) + "MBEDTLS_BASE64_C", +#endif /* MBEDTLS_BASE64_C */ +#if defined(MBEDTLS_BIGNUM_C) + "MBEDTLS_BIGNUM_C", +#endif /* MBEDTLS_BIGNUM_C */ +#if defined(MBEDTLS_BLOWFISH_C) + "MBEDTLS_BLOWFISH_C", +#endif /* MBEDTLS_BLOWFISH_C */ +#if defined(MBEDTLS_CAMELLIA_C) + "MBEDTLS_CAMELLIA_C", +#endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_CCM_C) + "MBEDTLS_CCM_C", +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CERTS_C) + "MBEDTLS_CERTS_C", +#endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CIPHER_C) + "MBEDTLS_CIPHER_C", +#endif /* MBEDTLS_CIPHER_C */ +#if defined(MBEDTLS_CMAC_C) + "MBEDTLS_CMAC_C", +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_CTR_DRBG_C) + "MBEDTLS_CTR_DRBG_C", +#endif /* MBEDTLS_CTR_DRBG_C */ +#if defined(MBEDTLS_DEBUG_C) + "MBEDTLS_DEBUG_C", +#endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_DES_C) + "MBEDTLS_DES_C", +#endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_DHM_C) + "MBEDTLS_DHM_C", +#endif /* MBEDTLS_DHM_C */ +#if defined(MBEDTLS_ECDH_C) + "MBEDTLS_ECDH_C", +#endif /* MBEDTLS_ECDH_C */ +#if defined(MBEDTLS_ECDSA_C) + "MBEDTLS_ECDSA_C", +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_ECJPAKE_C) + "MBEDTLS_ECJPAKE_C", +#endif /* MBEDTLS_ECJPAKE_C */ +#if defined(MBEDTLS_ECP_C) + "MBEDTLS_ECP_C", +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_ENTROPY_C) + "MBEDTLS_ENTROPY_C", +#endif /* MBEDTLS_ENTROPY_C */ +#if defined(MBEDTLS_ERROR_C) + "MBEDTLS_ERROR_C", +#endif /* MBEDTLS_ERROR_C */ +#if defined(MBEDTLS_GCM_C) + "MBEDTLS_GCM_C", +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HAVEGE_C) + "MBEDTLS_HAVEGE_C", +#endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HMAC_DRBG_C) + "MBEDTLS_HMAC_DRBG_C", +#endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_MD_C) + "MBEDTLS_MD_C", +#endif /* MBEDTLS_MD_C */ +#if defined(MBEDTLS_MD2_C) + "MBEDTLS_MD2_C", +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + "MBEDTLS_MD4_C", +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + "MBEDTLS_MD5_C", +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + "MBEDTLS_MEMORY_BUFFER_ALLOC_C", +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_NET_C) + "MBEDTLS_NET_C", +#endif /* MBEDTLS_NET_C */ +#if defined(MBEDTLS_OID_C) + "MBEDTLS_OID_C", +#endif /* MBEDTLS_OID_C */ +#if defined(MBEDTLS_PADLOCK_C) + "MBEDTLS_PADLOCK_C", +#endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PEM_PARSE_C) + "MBEDTLS_PEM_PARSE_C", +#endif /* MBEDTLS_PEM_PARSE_C */ +#if defined(MBEDTLS_PEM_WRITE_C) + "MBEDTLS_PEM_WRITE_C", +#endif /* MBEDTLS_PEM_WRITE_C */ +#if defined(MBEDTLS_PK_C) + "MBEDTLS_PK_C", +#endif /* MBEDTLS_PK_C */ +#if defined(MBEDTLS_PK_PARSE_C) + "MBEDTLS_PK_PARSE_C", +#endif /* MBEDTLS_PK_PARSE_C */ +#if defined(MBEDTLS_PK_WRITE_C) + "MBEDTLS_PK_WRITE_C", +#endif /* MBEDTLS_PK_WRITE_C */ +#if defined(MBEDTLS_PKCS5_C) + "MBEDTLS_PKCS5_C", +#endif /* MBEDTLS_PKCS5_C */ +#if defined(MBEDTLS_PKCS11_C) + "MBEDTLS_PKCS11_C", +#endif /* MBEDTLS_PKCS11_C */ +#if defined(MBEDTLS_PKCS12_C) + "MBEDTLS_PKCS12_C", +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PLATFORM_C) + "MBEDTLS_PLATFORM_C", +#endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_RIPEMD160_C) + "MBEDTLS_RIPEMD160_C", +#endif /* MBEDTLS_RIPEMD160_C */ +#if defined(MBEDTLS_RSA_C) + "MBEDTLS_RSA_C", +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_SHA1_C) + "MBEDTLS_SHA1_C", +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + "MBEDTLS_SHA256_C", +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + "MBEDTLS_SHA512_C", +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SSL_CACHE_C) + "MBEDTLS_SSL_CACHE_C", +#endif /* MBEDTLS_SSL_CACHE_C */ +#if defined(MBEDTLS_SSL_COOKIE_C) + "MBEDTLS_SSL_COOKIE_C", +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_TICKET_C) + "MBEDTLS_SSL_TICKET_C", +#endif /* MBEDTLS_SSL_TICKET_C */ +#if defined(MBEDTLS_SSL_CLI_C) + "MBEDTLS_SSL_CLI_C", +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + "MBEDTLS_SSL_SRV_C", +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_TLS_C) + "MBEDTLS_SSL_TLS_C", +#endif /* MBEDTLS_SSL_TLS_C */ +#if defined(MBEDTLS_THREADING_C) + "MBEDTLS_THREADING_C", +#endif /* MBEDTLS_THREADING_C */ +#if defined(MBEDTLS_TIMING_C) + "MBEDTLS_TIMING_C", +#endif /* MBEDTLS_TIMING_C */ +#if defined(MBEDTLS_VERSION_C) + "MBEDTLS_VERSION_C", +#endif /* MBEDTLS_VERSION_C */ +#if defined(MBEDTLS_X509_USE_C) + "MBEDTLS_X509_USE_C", +#endif /* MBEDTLS_X509_USE_C */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + "MBEDTLS_X509_CRT_PARSE_C", +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_X509_CRL_PARSE_C) + "MBEDTLS_X509_CRL_PARSE_C", +#endif /* MBEDTLS_X509_CRL_PARSE_C */ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + "MBEDTLS_X509_CSR_PARSE_C", +#endif /* MBEDTLS_X509_CSR_PARSE_C */ +#if defined(MBEDTLS_X509_CREATE_C) + "MBEDTLS_X509_CREATE_C", +#endif /* MBEDTLS_X509_CREATE_C */ +#if defined(MBEDTLS_X509_CRT_WRITE_C) + "MBEDTLS_X509_CRT_WRITE_C", +#endif /* MBEDTLS_X509_CRT_WRITE_C */ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + "MBEDTLS_X509_CSR_WRITE_C", +#endif /* MBEDTLS_X509_CSR_WRITE_C */ +#if defined(MBEDTLS_XTEA_C) + "MBEDTLS_XTEA_C", +#endif /* MBEDTLS_XTEA_C */ +#endif /* MBEDTLS_VERSION_FEATURES */ + NULL +}; + +int mbedtls_version_check_feature( const char *feature ) +{ + const char **idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* MBEDTLS_VERSION_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509.c ************/ + +/* + * X.509 common functions for parsing and verification + * + * 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) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_USE_C) + + + + + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) +#include +#include +#include +#endif +#endif + +#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + if( *p == end ) + return( 0 ); + + ext->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) + return( ret ); + + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + SYSTEMTIME st; + + GetSystemTime( &st ); + + now->year = st.wYear; + now->mon = st.wMonth; + now->day = st.wDay; + now->hour = st.wHour; + now->min = st.wMinute; + now->sec = st.wSecond; + + return( 0 ); +} +#else +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt; + mbedtls_time_t tt; + int ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + tt = mbedtls_time( NULL ); + lt = gmtime( &tt ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + + + + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + int ret; + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + mbedtls_x509_crt_init( &cacert ); + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); + + return( 0 ); +#else + ((void) verbose); + return( 0 ); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_create.c ************/ + +/* + * X.509 base functions for creating certificates / CSRs + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_CREATE_C) + + + + + +#include + +typedef struct { + const char *name; + size_t name_len; + const char*oid; +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, + { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, + { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, + { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, + { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, + { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, + { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, + { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, + { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, + { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, + { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, + { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, + { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, + { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, + { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, + { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, + { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, + { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, + { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, + { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, + { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, + { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, + { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, + { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, + { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, + { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, + { NULL, 0, NULL } +}; + +static const char *x509_at_oid_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncmp( cur->name, name, name_len ) == 0 ) + break; + + return( cur->oid ); +} + +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + int in_tag = 1; + char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + mbedtls_asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) + { + ret = MBEDTLS_ERR_X509_UNKNOWN_OID; + goto exit; + } + + s = c + 1; + in_tag = 0; + d = data; + } + + if( !in_tag && *c == '\\' && c != end ) + { + c++; + + /* Check for valid escaped characters */ + if( c == end || *c != ',' ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + const unsigned char *name, size_t name_len ) +{ + int ret; + size_t len = 0; + + // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL + // + if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && + memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, + (const char *) name, + name_len ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, + (const char *) name, + name_len ) ); + } + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret; + size_t len = 0; + mbedtls_asn1_named_data *cur = first; + + while( cur != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, + cur->oid.len, + cur->val.p, cur->val.len ) ); + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret; + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret; + size_t len = 0; + mbedtls_asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* MBEDTLS_X509_CREATE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_crl.c ************/ + +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * 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) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + + + + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.tag = **p; + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p = NULL, *end = NULL; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_crt.c ************/ + +/* + * X.509 certificate parsing and verification + * + * 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) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + + + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + /* Allow SHA-1 (weak, but still safe in controlled environments) */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | +#endif + /* Only SHA-2 hashes */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk_alg acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg, + const mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( ret ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we only parse and use dNSName at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + /* Skip everything but DNS name */ + if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + extn_oid.tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.p = *p; + *p += extn_oid.len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + // Use the original buffer until we figure out actual length + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + // Create and populate a new buffer for the raw field + crt->raw.len = crt_end - buf; + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, crt->raw.len ); + + // Direct pointers to the new buffer + p += crt->raw.len - len; + end = crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + const char *sep = ""; + size_t sep_len = 0; + + while( cur != NULL ) + { + if( cur->buf.len + sep_len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + n -= cur->buf.len + sep_len; + for( i = 0; i < sep_len; i++ ) + *p++ = sep[i]; + for( i = 0; i < cur->buf.len; i++ ) + *p++ = cur->buf.p[i]; + + sep = ", "; + sep_len = 2; + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & type ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & code ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation is no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + crl_list->issuer_raw.len != ca->subject_raw.len || + memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, + crl_list->issuer_raw.len ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); + + if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( 0 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + * bottom means child is the end entity cert + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top, int bottom ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + /* Exception: self-signed end-entity certs that are locally trusted. */ + if( top && bottom && + child->raw.len == parent->raw.len && + memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) + { + need_ca_bit = 0; + } + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +static int x509_crt_verify_top( + mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, int self_cnt, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + uint32_t ca_flags = 0; + int check_path_cnt; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_x509_crt *future_past_ca = NULL; + + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* + * Child is the top of the chain. Check against the trust_ca list. + */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown', no need to try any CA + */ + trust_ca = NULL; + } + else + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + + for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) + { + if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) + continue; + + check_path_cnt = path_cnt + 1; + + /* + * Reduce check_path_cnt to check against if top of the chain is + * the same as the trusted CA + */ + if( child->subject_raw.len == trust_ca->subject_raw.len && + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) == 0 ) + { + check_path_cnt--; + } + + /* Self signed certificates do not count towards the limit */ + if( trust_ca->max_pathlen > 0 && + trust_ca->max_pathlen < check_path_cnt - self_cnt ) + { + continue; + } + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + continue; + } + + if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) || + mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + { + if ( future_past_ca == NULL ) + future_past_ca = trust_ca; + + continue; + } + + break; + } + + if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) + { + /* + * Top of chain is signed by a trusted CA + */ + *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + } + + /* + * If top of chain is not the same as the trusted CA send a verify request + * to the callback for any issues with validity and CRL presence for the + * trusted CA certificate. + */ + if( trust_ca != NULL && + ( child->subject_raw.len != trust_ca->subject_raw.len || + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) != 0 ) ) + { +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the chain's top crt */ + *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); +#else + ((void) ca_crl); +#endif + + if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) + ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, + &ca_flags ) ) != 0 ) + { + return( ret ); + } + } + } + + /* Call callback on top cert */ + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + } + + *flags |= ca_flags; + + return( 0 ); +} + +static int x509_crt_verify_child( + mbedtls_x509_crt *child, mbedtls_x509_crt *parent, + mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, int self_cnt, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + uint32_t parent_flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + mbedtls_x509_crt *grandparent; + const mbedtls_md_info_t *md_info; + + /* Counting intermediate self signed certificates */ + if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + self_cnt++; + + /* path_cnt is 0 for the first intermediate CA */ + if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately as the goal is to avoid unbounded recursion */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + else + { + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + + if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + } + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); +#endif + + /* Look for a grandparent in trusted CAs */ + for( grandparent = trust_ca; + grandparent != NULL; + grandparent = grandparent->next ) + { + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + if( grandparent != NULL ) + { + ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, + path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + /* Look for a grandparent upwards the chain */ + for( grandparent = parent->next; + grandparent != NULL; + grandparent = grandparent->next ) + { + /* +2 because the current step is not yet accounted for + * and because max_pathlen is one higher than it should be. + * Also self signed certificates do not count to the limit. */ + if( grandparent->max_pathlen > 0 && + grandparent->max_pathlen < 2 + path_cnt - self_cnt ) + { + continue; + } + + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + /* Is our parent part of the chain or at the top? */ + if( grandparent != NULL ) + { + ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, + profile, path_cnt + 1, self_cnt, &parent_flags, + f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, + path_cnt + 1, self_cnt, &parent_flags, + f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + } + + /* child is verified to be a child of the parent, call verify callback */ + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + + *flags |= parent_flags; + + return( 0 ); +} + +/* + * Verify the certificate validity + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); +} + + +/* + * Verify the certificate validity, with profile + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + size_t cn_len; + int ret; + int pathlen = 0, selfsigned = 0; + mbedtls_x509_crt *parent; + mbedtls_x509_name *name; + mbedtls_x509_sequence *cur = NULL; + mbedtls_pk_type_t pk_type; + + *flags = 0; + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + if( cn != NULL ) + { + name = &crt->subject; + cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + cur = &crt->subject_alt_names; + + while( cur != NULL ) + { + if( cur->buf.len == cn_len && + x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) + break; + + if( cur->buf.len > 2 && + memcmp( cur->buf.p, "*.", 2 ) == 0 && + x509_check_wildcard( cn, &cur->buf ) == 0 ) + { + break; + } + + cur = cur->next; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + while( name != NULL ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) + { + if( name->val.len == cn_len && + x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) + break; + + if( name->val.len > 2 && + memcmp( name->val.p, "*.", 2 ) == 0 && + x509_check_wildcard( cn, &name->val ) == 0 ) + break; + } + + name = name->next; + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + } + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Look for a parent in trusted CAs */ + for( parent = trust_ca; parent != NULL; parent = parent->next ) + { + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + } + + if( parent != NULL ) + { + ret = x509_crt_verify_top( crt, parent, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + goto exit; + } + else + { + /* Look for a parent upwards the chain */ + for( parent = crt->next; parent != NULL; parent = parent->next ) + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + + /* Are we part of the chain or at the top? */ + if( parent != NULL ) + { + ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + goto exit; + } + else + { + ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + goto exit; + } + } + +exit: + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509_csr.c ************/ + +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * 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) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + + + + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( csr->version != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + csr->version++; + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) + return( ret ); + + mbedtls_pem_free( &pem ); + return( 0 ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509write_crt.c ************/ + +/* + * X.509 certificate writing + * + * 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) + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + + + + + + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) + +#endif /* MBEDTLS_PEM_WRITE_C */ + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); + + mbedtls_mpi_init( &ctx->serial ); + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) +{ + mbedtls_mpi_free( &ctx->serial ); + + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->issuer ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); +} + +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) +{ + ctx->version = version; +} + +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) +{ + ctx->subject_key = key; +} + +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) +{ + ctx->issuer_key = key; +} + +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ) +{ + return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) +{ + int ret; + + if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ); +} + +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); + } + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ); +} + +#if defined(MBEDTLS_SHA1_C) +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof( buf ); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[4], ku; + unsigned char *c; + int ret; + + /* We currently only support 7 bits, from 0x80 to 0x02 */ + if( ( key_usage & ~0xfe ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 4; + ku = (unsigned char) key_usage; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *t, size_t size ) +{ + int ret; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + /* Signature algorithm needed in TBS, and later for actual signature */ + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + } + + /* + * SubjectPublicKeyInfo + */ + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* + * Write data to output buffer + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + if( len > (size_t)( c2 - buf ) ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/x509write_csr.c ************/ + +/* + * X.509 Certificate Signing Request writing + * + * 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) + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + + + + + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) + +#endif + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) +{ + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + + if( len ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Prepare signature + */ + mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Write data to output buffer + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + if( len > (size_t)( c2 - buf ) ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + + +/********* Start of file library/xtea.c ************/ + +/* + * An 32-bit implementation of the XTEA algorithm + * + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_XTEA_C) + + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_XTEA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +/* zeroize was here */ + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); +} + +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(mbedtls_xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + GET_UINT32_BE( ctx->k[i], key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, + const unsigned char input[8], unsigned char output[8]) +{ + uint32_t *k, v0, v1, i; + + k = ctx->k; + + GET_UINT32_BE( v0, input, 0 ); + GET_UINT32_BE( v1, input, 4 ); + + if( mode == MBEDTLS_XTEA_ENCRYPT ) + { + uint32_t sum = 0, delta = 0x9E3779B9; + + for( i = 0; i < 32; i++ ) + { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + } + } + else /* MBEDTLS_XTEA_DECRYPT */ + { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for( i = 0; i < 32; i++ ) + { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } + } + + PUT_UINT32_BE( v0, output, 0 ); + PUT_UINT32_BE( v1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, + unsigned char iv[8], const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* !MBEDTLS_XTEA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * XTEA tests vectors (non-official) + */ + +static const unsigned char xtea_test_key[6][16] = +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char xtea_test_pt[6][8] = +{ + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const unsigned char xtea_test_ct[6][8] = +{ + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +/* + * Checkup routine + */ +int mbedtls_xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + mbedtls_xtea_context ctx; + + mbedtls_xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); + mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_xtea_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_XTEA_C */ + +/* + Amalgamated build undefines + */ + +#undef ADD +#undef BC +#undef BEFORE_COLON +#undef F +#undef F0 +#undef F1 +#undef F2 +#undef F3 +#undef F4 +#undef F5 +#undef FSb +#undef K +#undef KK +#undef P +#undef R +#undef ROTR +#undef S +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef SAFE_SNPRINTF +#undef SHR +#undef close +#undef read +#undef supported_init +#undef write + + +#endif /* ME_COM_MBEDTLS */ diff --git a/code/application/source/sf_app/code/source/utils/sf_aes.c b/code/application/source/sf_app/code/source/utils/sf_aes.c new file mode 100755 index 000000000..209d2ed4b --- /dev/null +++ b/code/application/source/sf_app/code/source/utils/sf_aes.c @@ -0,0 +1,169 @@ + + +#if 1 + +#include +#include + +#include "mbedtls.h" +#include "sf_aes.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + + + +/* + # padding with pkcs7 AES_128_CBC Encrypt + ptx = "CBC has been the most commonly used mode of operation." + key = 06a9214036b8a15b512e03d534120006 + iv = 3dafba429d9eb430b422da802c9fac41 + ctx = 4DDF9012D7B3898745A1ED9860EB0FA2 + FD2BBD80D27190D72A2F240C8F372A27 + 63746296DDC2BFCE7C252B6CD7DD4BA8 + 577E096DBD8024C8B4C5A1160CA2D3F9 +*/ + +#define mbedtls_printf printf + +UINT32 i = 0; + +//UINT8 *inputData = (UINT8 *)"CBC has been the most commonly used mode of operation."; + +//UINT8 key[16] = "000000000000000"; +//UINT8 iv[16] = "000000000000000"; + +UINT8 key[16] = { +'S','T','1','Y','C','S','Y','R','Y','O','0','1','Y','0','0','S' +}; + +UINT8 iv[16] = { +'S','T','1','Y','C','S','Y','R','Y','O','0','1','Y','0','1','S' +}; + + + + + +/* +static void dump_buf(UINT8 *info, UINT8 *buf, UINT32 len) +{ + mbedtls_printf("%s", info); + for(i = 0; i < len; i++) + { + mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n\t":" ", + buf[i], i == len - 1 ? "\n":""); + } + mbedtls_printf("\n"); +} +*/ +/*********************************************** +aesType:MBEDTLS_CIPHER_AES_128_CBC +operation:MBEDTLS_ENCRYPT/MBEDTLS_DECRYPT +***********************************************/ +UINT32 sf_cipher(UINT32 aesType,UINT8 operation,UINT8 *input,UINT8 *output, UINT8 srcl) +{ + size_t len = 0; + size_t olen = 0; + //int ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *info; + + //mbedtls_platform_set_printf(printf); +// mbedtls_printf("sf_cipher len %d", srcl); + + mbedtls_cipher_init(&ctx); + info = mbedtls_cipher_info_from_type(aesType); + if(info == NULL) + { + mbedtls_printf("mbedtls_cipher_info_from_type error"); + + } + //ret = mbedtls_cipher_setup(&ctx, info); + mbedtls_cipher_setup(&ctx, info); +// mbedtls_printf("\n mbedtls_cipher_setup %d\n", ret); + +// mbedtls_printf("\n cipher info setup, name: %s, block size: %d\n", +// mbedtls_cipher_get_name(&ctx), +// mbedtls_cipher_get_block_size(&ctx)); + + mbedtls_cipher_setkey(&ctx, key, sizeof(key)*8, operation); + mbedtls_cipher_set_iv(&ctx, iv, sizeof(iv)); + //mbedtls_cipher_update(&ctx, input, strlen((char *)input), output, &len); + mbedtls_cipher_update(&ctx, input, srcl, output, &len); + olen += len; + + mbedtls_cipher_finish(&ctx, output + len, &len); + olen += len; + +// dump_buf((UINT8 *)"\n cipher aes encrypt:", output, olen); + + mbedtls_cipher_free(&ctx); + return olen; +} + + + +#if 0 +void sf_cipher_test(void) +{ + UINT8 outputData[64] = {0}; + UINT8 inputData[64] = {0}; + sf_cipher(MBEDTLS_CIPHER_AES_128_CBC,MBEDTLS_ENCRYPT,inputData,outputData); + sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData,outputData); + + +} +#else +void sf_cipher_test(void) //use cbc way, the output is integer multiple of 16 bytes of input +{ + UINT8 outputData[128] = {0}; + UINT8 inputData[128] = "abc";//"CBC has been the most commonly used mode of operation."; + sf_cipher(MBEDTLS_CIPHER_AES_128_CBC,MBEDTLS_ENCRYPT,inputData, outputData, strlen((char *)inputData)); + + mbedtls_printf("cbc test\r\n"); + mbedtls_printf("after encode %s", outputData); + + memset(inputData, 0x00, sizeof(inputData)); + sf_cipher(MBEDTLS_CIPHER_AES_128_CBC,MBEDTLS_DECRYPT,outputData, inputData, strlen((char *)outputData)); + + printf("after decode %s", inputData); + //sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData,outputData); + + +} + +void sf_cipher_test1(void) //use ctr way, the output is as large as the input +{ + UINT8 outputData[128] = {0}; + UINT8 inputData[128] = "1111111111111111";//"CBC has been the most commonly used mode of operation."; + sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData, outputData, strlen((char *)inputData)); + + mbedtls_printf("ctr test\r\n"); + mbedtls_printf("after encode %s", outputData); + + memset(inputData, 0x00, sizeof(inputData)); + sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_DECRYPT,outputData, inputData, strlen((char *)outputData)); + + printf("after decode %s", inputData); + //sf_cipher(MBEDTLS_CIPHER_AES_128_CTR,MBEDTLS_ENCRYPT,inputData,outputData); + + +} + +#endif + +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/utils/sf_qrutils.c b/code/application/source/sf_app/code/source/utils/sf_qrutils.c new file mode 100755 index 000000000..c6ff2a113 --- /dev/null +++ b/code/application/source/sf_app/code/source/utils/sf_qrutils.c @@ -0,0 +1,236 @@ + + +#include +#include + + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +static char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static char * base64_encode(const unsigned char * bindata, char * base64, int binlength, int model) +{ + int i, j; + unsigned char current; + + for (i = 0, j = 0; i < binlength; i += 3) + { + current = (bindata[i] >> 2); + current &= (unsigned char)0x3F; + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30); + if (i + 1 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C); + if (i + 2 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F); + base64[j++] = base64char[(int)current]; + } + if(model) + { + base64[j++] = '\n'; + } + base64[j] = '\0'; + return base64; +} + +static int base64_decode(const char * base64, unsigned char * bindata) +{ + int i, j; + unsigned char k; + unsigned char temp[4]; + for (i = 0, j = 0; base64[i] != '\0'; i += 4) + { + memset(temp, 0xFF, sizeof(temp)); + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i]) + temp[0] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 1]) + temp[1] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 2]) + temp[2] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 3]) + temp[3] = k; + } + + bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2)) & 0xFC)) | + ((unsigned char)((unsigned char)(temp[1] >> 4) & 0x03)); + if (base64[i + 2] == '=') + break; + + bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4)) & 0xF0)) | + ((unsigned char)((unsigned char)(temp[2] >> 2) & 0x0F)); + if (base64[i + 3] == '=') + break; + + bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6)) & 0xF0)) | + ((unsigned char)(temp[3] & 0x3F)); + } + return j; +} + + +static int URLEncode(const char* str, const int strSize, char* result, const int resultSize) +{ + int i; + int j = 0;//for result index + char ch; + + if ((str == 0) || (result == 0) || (strSize <= 0) || (resultSize <= 0)) { + return 0; + } + + for (i = 0; (i= 'A') && (ch<='Z')) || + ((ch >= 'a') && (ch<='z')) || + ((ch >= '0') && (ch<='9'))) { + result[j++] = ch; + } + else if (ch == ' ') { + result[j++] = '+'; + } + else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') { + result[j++] = ch; + } + else { + if (j + 3 < resultSize) { + sprintf(result + j, "%%%02X", (unsigned char)ch); + j += 3; + } + else { + return 0; + } + } + } + + result[j] = '\0'; + return j; +} + + +static void urldecode(char *p) +{ + //register i = 0; + volatile int i = 0; + while (*(p + i)) + { + if ((*p = *(p + i)) == '%') + { + *p = *(p + i + 1) >= 'A' ? ((*(p + i + 1) & 0XDF) - 'A') + 10 : (*(p + i + 1) - '0'); + *p = (*p) * 16; + *p += *(p + i + 2) >= 'A' ? ((*(p + i + 2) & 0XDF) - 'A') + 10 : (*(p + i + 2) - '0'); + i += 2; + } + else if (*(p + i) == '+') + { + *p = ' '; + } + p++; + } + *p = '\0'; +} + + +static void strConv(char *p) +{ + int i; + int len = strlen(p); + char temp; + + for (i = 0; i < len; ) + { + temp = *(p + i); + if (*(p + i + 1) != '\0') + { + *(p + i) = *(p + i + 1); + *(p + i + 1) = temp; + } + i += 2; + } +} + + +char* nfc_qrencrypt(char *content) +{ + char encodeStr[512] = { 0 }; + + char encodeUrlStr[512] = { 0 }; + + base64_encode((unsigned char *)content, encodeStr, strlen(content), 0); + + strConv(encodeStr); + + URLEncode(encodeStr, strlen(encodeStr), encodeUrlStr, 256); + + strcpy(content, encodeUrlStr); + + return content; +} + + + +char * nfc_qrdecrypt(char * content) +{ + + char decodeStr[512] = { 0 }; + + char decodeUrlStr[512] = { 0 }; + + strcpy(decodeUrlStr, content); + + urldecode(decodeUrlStr); + + strConv(decodeUrlStr); + + base64_decode(decodeUrlStr, (unsigned char *)decodeStr); + + strcpy(content, decodeStr); + + return content; + + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/code/source/utils/sf_qrutils.o b/code/application/source/sf_app/code/source/utils/sf_qrutils.o new file mode 100644 index 0000000000000000000000000000000000000000..4cf5fc88ad7fa0bc362a2094caa1b5780d59e190 GIT binary patch literal 3348 zcma)8Z){W76+ibqCpgB-UPz*bE}9+;whWrL8#f(vE3F-uvbLcZ(smS(APJ^qO&m8i z9q?sN!l<-i;<0{e8}T}A-y^Lb_N9^ws)ROCt%Ox;a+-v1HBZTDZ*>c>PW z-zdCwO&D=cGf#QKc-s$2+trL&N0`e>lk*C8ar+R0ikh&SxrITCCYxKUuD{d$t?Gx^&vTqgWS(>q@g{y$G=M z(yXV&=e&?H>xGuU?U%hi@2nf1wcW5$RE+&lA?$?;Mb%~?X9e5s$`+MyE~rS>c6DdY zGvME9`2Bvh`s$^q`y0ji;d!k-g_Jh{zY1@h zSF51gT(bR$z2NjB<~BOue}(AP#KT3;M2*6zRlhOhQF-1GRM4W*7IZGz(uUk^!umnl z(M7|0&UkZ(<$x9<3i%BKxwpiuSs&y9m4GD%XVPuv^V`=G71RJU)wz zdB>C&d|4jy5;Eznh0X7))gRIN1Zr9EKCV`8B`nyQbLgQthhlNniaZ6iXP)?=h~6oB zw-?^JsV^102-d5#-zPfle1e>D4pzhN8n8HbZ-RHpMHMM=?H5(M4LoBWKF@ot@aceg zUM1cwdWpZ_-0~SO?40%5%4ZzSTyTVO)`^%`D!M%D(9$Vq8zKK2h82Yp7)iAV?9h_! zz6MUf*HItT!PgAizX@GQBg*4)J&L<@SKl8(pJwm${pnpr_*1W6(Dy+-IsRady!xD< zE?HEZBaTa#oTm}R`L-H8Z^DOFsJAZPt89i|&`?Vk_mIS0Fs@VxwcG$(-Va~l_m#>< zwv!h=WZiAtRbApf%ViaZo^@SiKC7;amS<7Ni}O+@&ux*(xt#p#pY)jRG8b}4Y31wK zcfjX8QM?PxHRCBXMqvk(fg-0Ux&VOf4St`z?M)$ZYhrd9l{lJ+T|L*v8Y!w1vu=rAsKvrp`gUgG`##D4Z+zYAP(^1t|?!-qBH z`o2!a!CtZSNo^mW`+58J#N0|J_O-k7?l#)%lk<-H1>%YxT2!mxdn<4_Pt2R|mczvQ>XezJdkt>ufPkhzzYYaHLg>nwth#s5-)mZ2{WDW z(l?P#U!box$p+^A4f#{Vum4-t12^M@Mxr_lnvcw`SShuv2A)!RdKh&hVIwbGFm_E$%`{@##R z;>8&c`vx0$OU!Z3HO7HHz#%JlVk$p62A-d(^P|BmpFW-^>+ooPl&rB_j;xvVq{T|M zttI7-=I&Ii)Cb{PGt&%b-DS;a1J)o}7XQwrq z&(BPZ9m}V4i0uEPFTo69qburE|L@rlz<7;m9R|;X+x2;NUxN+T?|<3J243^Id>;b} zZsmPY;6D+?8w-697@zMn+wfp{2%|ZU0%Y#@fC9XSp=idF5K_=F9{UpD?Zdno?>GYD zehMhSdlrgjyaI%+&@mqS72stsXS^5&(@`AuWPMuuWjkK~af5Syn0^U6t3Iv$vJH<{ z8oZ{&4?YNY5!*2R90RUrYXW}Q?twr65A2vXg-1QOUwj|F2tBS?Ee->mV-0GHDP2O4 X2YJ$<0FU3;X1iZu +#include +#include +#include +#include +#include "iot_import.h" + +// #define STATE_SUCCESS 0 +#define STATE_FAILED -1 +#define STATE_USER_INPUT_UNKNOWN_OPTION (-0x0103) +// #define STATE_USER_INPUT_OUT_RANGE (-0x0102) +#define STATE_SYS_DEPEND_MALLOC_FAILED (-0x0201) + + +/** + * @brief authorize option, all mandatory option shall be setup + * + */ +typedef enum { + AUTHORIZEOPT_MQTT_HANDLE, /**< dataType:(void *), mqtt handle, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_MAC, /**< dataType:(char *), authorize mac/sn..., @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_CODE, /**< dataType:(char *), authorize code, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_REQUEST, /**< dataType:(char *), authorize request, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_PARSE, /**< dataType:(char *), authorize reply data parse, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_CHECK, /**< dataType:(char *), authorize check, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_CHECK_CB, /**< dataType:(char *), pointer check result callback, @b mandatory option */ + AUTHORIZEOPT_AUTHORIZE_RW_CB, /**< dataType:(authorize_cb_t), pointer data read/write function */ + AUTHORIZEOPT_MAX +} aiot_authorize_option_t; + +typedef int32_t(*authorize_check_cb_t)(char *random, char* digest); +typedef int32_t(*authorize_rw_cb_t)(char *data, int32_t rw); + +typedef struct { + void *mqtt_handle; + void *mutex; + authorize_check_cb_t check_result_cb; + authorize_rw_cb_t auth_rw_cb; + char *mac; + char *authcode; + uint8_t authcode_count; + uint8_t req_count; + uint8_t req_success; +} aiot_authorize_handle_t; + + +/** + * @brief initializes the authorize module + * + * @return void* + * @retval Not NULL handle of authorize module + * @retval NULL initializes failed, system callbacks not complete or malloc failed. + * + * @brief + * @brief -------------------------------------------------- + * + * @brief 初始化授权模块 + * + * @return void* + * @retval Not NULL 授权模块句柄 + * @retval NULL 初始化失败, 系统回调不完整或者内存分配失败. + * + */ +void *aiot_authorize_open(void *mqtt_handle); + +/** + * @brief set option of authorize moduel + * + * @param[in] handle handle of authorize module + * @param[in] option the configuration option, see @ref aiot_authorize_option_t + * @param[in] data the configuration data, see @ref aiot_authorize_option_t + * + * @return int32_t + * @retval ERRCODE_SUCCESS set option successfully + * @retval 0, reserved for other usage */ + +} iotx_err_t; +/* From utils_error.h */ + +#if defined(__cplusplus) +} +#endif +#endif /* __IOT_EXPORT_ERRNO__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_event.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_event.h new file mode 100755 index 000000000..d6b671d63 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_event.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef IOTX_EXPORT_EVENT_H +#define IOTX_EXPORT_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief event list used for iotx_regist_event_monitor_cb + */ +enum iotx_event_t { + IOTX_AWSS_START = 0x1000, // AWSS start without enbale, just supports device discover + IOTX_AWSS_ENABLE, // AWSS enable + IOTX_AWSS_LOCK_CHAN, // AWSS lock channel(Got AWSS sync packet) + IOTX_AWSS_CS_ERR, // AWSS AWSS checksum is error. For dev ap is awss packet content error + IOTX_AWSS_PASSWD_ERR, // AWSS decrypt passwd error + IOTX_AWSS_GOT_SSID_PASSWD, // AWSS parse ssid and passwd successfully + IOTX_AWSS_CONNECT_ADHA, // AWSS try to connnect adha (device discover, router solution) + IOTX_AWSS_CONNECT_ADHA_FAIL, // AWSS fails to connect adha + IOTX_AWSS_CONNECT_AHA, // AWSS try to connect aha (AP solution) + IOTX_AWSS_CONNECT_AHA_FAIL, // AWSS fails to connect aha + IOTX_AWSS_SETUP_NOTIFY, // AWSS sends out device setup information (AP and router solution) + IOTX_AWSS_CONNECT_ROUTER, // AWSS try to connect destination router + IOTX_AWSS_CONNECT_ROUTER_FAIL, // AWSS fails to connect destination router. + IOTX_AWSS_GOT_IP, // AWSS connects destination successfully and got ip address + IOTX_AWSS_SUC_NOTIFY, // AWSS sends out success notify (AWSS sucess) + IOTX_AWSS_BIND_NOTIFY, // AWSS sends out bind notify information to support bind between user and device + IOTX_AWSS_ENABLE_TIMEOUT, // AWSS enable timeout(user needs to call awss_config_press again to enable awss) + IOTX_CONN_CLOUD = 0x2000, // Device try to connect cloud + IOTX_CONN_CLOUD_FAIL, // Device fails to connect cloud, refer to net_sockets.h for error code + IOTX_CONN_CLOUD_SUC, // Device connects cloud successfully + IOTX_CONN_REPORT_TOKEN_SUC, // Device report token to cloud success + IOTX_RESET = 0x3000, // Linkkit reset success (just got reset response from cloud without any other operation) +}; + +/** + * @brief register callback to monitor all event from system. + * + * @param callback, when some event occurs, the system will trigger callback to user. + * refer to enum iotx_event_t for event list supported. + * + * @return 0 when success, -1 when fail. + * @note: user should make sure that callback is not block and runs to complete fast. + */ +extern int iotx_event_regist_cb(void (*monitor_cb)(int event)); + +/** + * @brief post event to trigger callback resitered by iotx_event_regist_cb + * + * @param event, event id, refer to iotx_event_t + * + * @return 0 when success, -1 when fail. + */ +extern int iotx_event_post(int event); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* IOTX_EXPORT_H */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_guider.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_guider.h new file mode 100755 index 000000000..0e0a0cdf3 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_guider.h @@ -0,0 +1,33 @@ +#ifndef __IOT_EXPORT_GUIDER_H__ +#define __IOT_EXPORT_GUIDER_H__ + +#define GUIDER_ENV_LEN (10) +#define GUIDER_ENV_KEY "env" + +typedef enum _region_type_e +{ + REGION_TYPE_ID = 0, + REGION_TYPE_MQTTURL, + REGION_TYPE_MAX +} region_type_e; + +typedef enum _guider_env_e +{ + GUIDER_ENV_DAILY = 1, + GUIDER_ENV_PRERELEASE, + GUIDER_ENV_ONLINE, + GUIDER_ENV_MAX +} guider_env_e; + +DLL_IOT_API int iotx_guider_set_dynamic_mqtt_url(char *p_mqtt_url); +DLL_IOT_API int iotx_guider_set_dynamic_region(int region); +DLL_IOT_API int iotx_guider_clear_dynamic_url(void); +DLL_IOT_API int iotx_guider_fill_conn_string(char *dst, int len, const char *fmt, ...); +DLL_IOT_API int iotx_redirect_region_subscribe(void); +DLL_IOT_API int iotx_reconnect_region_subscribe(void); +DLL_IOT_API int iotx_guider_get_kv_env(void); +DLL_IOT_API guider_env_e iotx_guider_get_env(void); +DLL_IOT_API iotx_cloud_region_types_t iotx_guider_get_region(void); +DLL_IOT_API int iotx_guider_get_region_id(void); +DLL_IOT_API int guider_set_direct_connect_count(unsigned char count); +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http.h new file mode 100755 index 000000000..2f6aa6c31 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_HTTP_H_ +#define _IOT_EXPORT_HTTP_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* IoTx http initial param */ +typedef struct { + iotx_device_info_t *device_info; + int keep_alive; + int timeout_ms; +} iotx_http_param_t; + +/* IoTx http context */ +typedef struct { + char *p_auth_token; + uint32_t auth_token_len; + char is_authed; + const char *version; + const char *signmethod; + const char *sign; + iotx_device_info_t *p_devinfo; + const char *timestamp; + void *httpc; + int keep_alive; + int timeout_ms; +} iotx_http_t, *iotx_http_pt; + +/* IoTx http message definition + * request_payload and response_payload need to be allocate in order to save memory. + * topic_path specify the topic url you want to publish message. + */ +typedef struct { + char *topic_path; + uint32_t request_payload_len; + char *request_payload; + uint32_t response_payload_len; + char *response_payload; + uint32_t timeout_ms; +} iotx_http_message_param_t; + +/* The response code from sever */ +typedef enum { + IOTX_HTTP_SUCCESS = 0, + IOTX_HTTP_COMMON_ERROR = 10000, + IOTX_HTTP_PARAM_ERROR = 10001, + IOTX_HTTP_AUTH_CHECK_ERROR = 20000, + IOTX_HTTP_TOKEN_EXPIRED_ERROR = 20001, + IOTX_HTTP_TOKEN_NULL_ERROR = 20002, + IOTX_HTTP_TOKEN_CHECK_ERROR = 20003, + IOTX_HTTP_UPDATE_SESSION_ERROR = 20004, + IOTX_HTTP_PUBLISH_MESSAGE_ERROR = 30001, + IOTX_HTTP_REQUEST_TOO_MANY_ERROR = 40000, +} iotx_http_upstream_response_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_http http + * @{ + */ + +/** + * @brief Initialize the HTTP client + * This function initialize the data. + * + * @param [in] pInitParams: Specify the init param infomation. + * + * @retval NULL : Initialize failed. + * @retval NOT_NULL : The contex of HTTP client. + * @see None. + */ +DLL_IOT_API void *IOT_HTTP_Init(iotx_http_param_t *pInitParams); + +/** + * @brief De-initialize the HTTP client + * This function release the related resource. + * + * @param [in] handle: pointer to http context pointer. + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_HTTP_DeInit(void **handle); + +/** + * @brief Handle device name authentication with remote server. + * + * @param [in] handle: Pointer of context, specify the HTTP client. + * + * @retval 0 : Authenticate success. + * @retval -1 : Authenticate failed. + * @see iotx_err_t. + */ +DLL_IOT_API int IOT_HTTP_DeviceNameAuth(void *handle); + +/** + * @brief Send a message with specific path to server. + * Client must authentication with server before send message. + * + * @param [in] handle: Pointer of contex, specify the HTTP client. + * @param [in] msg_param: Specify the topic path and http payload configuration. + * + * @retval 0 : Success. + * @retval -1 : Failed. + * @see iotx_err_t. + */ +DLL_IOT_API int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param); + +/** + * @brief close tcp connection from client to server. + * + * @param [in] handle: Pointer of contex, specify the HTTP client. + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_HTTP_Disconnect(void *handle); + +/** @} */ /* end of api_http */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2.h new file mode 100755 index 000000000..4a9ea38e7 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef IOT_EXPORT_HTTP2_H +#define IOT_EXPORT_HTTP2_H + +#ifdef __cplusplus +extern "C" { +#endif +typedef enum { + + HTTP2_FLAG_NONE = 0, + + HTTP2_FLAG_END_STREAM = 0x01, + +} http2_flag; + +typedef struct http2_list_s { + struct http2_list_s *prev; + struct http2_list_s *next; +} http2_list_t; + +typedef void (*on_user_header_callback)(int32_t stream_id, int cat, const uint8_t *name, uint32_t namelen, + const uint8_t *value, uint32_t valuelen, uint8_t flags); + +typedef void (*on_user_chunk_recv_callback)(int32_t stream_id, + const uint8_t *data, uint32_t len, uint8_t flags); + +typedef void (*on_user_stream_close_callback)(int32_t stream_id, uint32_t error_code); + +typedef void (*on_user_frame_send_callback)(int32_t stream_id, int type, uint8_t flags); + +typedef void (*on_user_frame_recv_callback)(int32_t stream_id, int type, uint8_t flags); + +typedef struct { + on_user_header_callback on_user_header_cb; + on_user_chunk_recv_callback on_user_chunk_recv_cb; + on_user_stream_close_callback on_user_stream_close_cb; + on_user_frame_send_callback on_user_frame_send_cb; + on_user_frame_recv_callback on_user_frame_recv_cb; +} http2_user_cb_t; + +typedef struct http2_connection { + void *network; /* iot network ptr */ + void *session; /* http2 session */ + int flag; /* check the stream is end or not */ + int status; + http2_user_cb_t *cbs; +} http2_connection_t; + +typedef struct http2_header_struct { + char *name; /* header name */ + char *value; /* the value of name */ + int namelen; /* the length of header name */ + int valuelen; /* the length of value */ +} http2_header; + +typedef struct http2_data_struct { + http2_header *header; /* header data. */ + int header_count; /* the count of header data. */ + char *data; /* send data. */ + int len; /* send data length. */ + int stream_id; /* send data over specify stream */ + int flag; /* send data flag. */ +} http2_data; + +/** +* @brief the http2 client connect. +* @param[in] pclient: http client. +* @return http2 client connection handler. +*/ +extern http2_connection_t *iotx_http2_client_connect(void *pclient, char *url, int port); + +http2_connection_t *iotx_http2_client_connect_with_cb(void *pclient, char *url, int port, http2_user_cb_t *cb); +/** +* @brief the http2 client send data. +* @param[in] handler: http2 client connection handler. +* @param[in] data: send data. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_send(http2_connection_t *conn, http2_data *h2_data); +/** +* @brief the http2 client receive data. +* @param[in] handler: http2 client connection handler. +* @param[in] data: receive data buffer. +* @param[in] data_len: buffer length. +* @param[in] len: receive data length. +* @param[in] timeout: receive data timeout. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_recv(http2_connection_t *conn, char *data, int data_len, int *len, int timeout); +/** +* @brief the http2 client connect. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_disconnect(http2_connection_t *conn); +/** +* @brief the http2 client send ping to keep alive. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_client_send_ping(http2_connection_t *conn); +/** +* @brief the http2 client get available windows size. +* @param[in] handler: http2 client connection handler. +* @return The window size. +*/ +extern int iotx_http2_get_available_window_size(http2_connection_t *conn); +/** +* @brief the http2 client receive windows size packet to update window. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_update_window_size(http2_connection_t *conn); +/** +* @brief the http2 client performs the network I/O. +* @param[in] handler: http2 client connection handler. +* @return The result. 0 is ok. +*/ +extern int iotx_http2_exec_io(http2_connection_t *connection); +#ifdef __cplusplus +} +#endif + +#endif /* IOT_EXPORT_HTTP2_H */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2_stream.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2_stream.h new file mode 100755 index 000000000..3b9005f5f --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_http2_stream.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef IOT_EXPORT_HTTP2_STREAM_H +#define IOT_EXPORT_HTTP2_STREAM_H + +#include "iot_export_http2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOT_HTTP2_RES_OVERTIME_MS (10000) +#define IOT_HTTP2_KEEP_ALIVE_CNT (2) +#define IOT_HTTP2_KEEP_ALIVE_TIME (30*1000) /* in seconds */ + +#define MAKE_HEADER(NAME, VALUE) \ + { \ + (char *) NAME, (char *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 \ + } + +#define MAKE_HEADER_CS(NAME, VALUE) \ + { \ + (char *) NAME, (char *)VALUE, strlen(NAME) , strlen(VALUE) \ + } + +typedef struct { + char *product_key; + char *device_name; + char *device_secret; + char *url; + int port; +} device_conn_info_t; + +typedef struct { + http2_header *nva; + int num; +} header_ext_info_t; + +typedef enum { + STREAM_TYPE_DOWNLOAD, + STREAM_TYPE_UPLOAD, + STREAM_TYPE_AUXILIARY, + STREAM_TYPE_NUM +} stream_type_t; + +typedef void (*on_stream_header_callback)(uint32_t stream_id, char *channel_id, int cat, const uint8_t *name, + uint32_t namelen, const uint8_t *value, uint32_t valuelen, uint8_t flags, void *user_data); + +typedef void (*on_stream_chunk_recv_callback)(uint32_t stream_id, char *channel_id, + const uint8_t *data, uint32_t len, uint8_t flags, void *user_data); + +typedef void (*on_stream_close_callback)(uint32_t stream_id, char *channel_id, uint32_t error_code, void *user_data); + +typedef void (*on_stream_frame_send_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags, void *user_data); + +typedef void (*on_stream_frame_recv_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags,void *user_data); + +typedef void (*on_reconnect_callback)(); +typedef void (*on_disconnect_callback)(); + +typedef struct { + on_stream_header_callback on_stream_header_cb; + on_stream_chunk_recv_callback on_stream_chunk_recv_cb; + on_stream_close_callback on_stream_close_cb; + on_stream_frame_send_callback on_stream_frame_send_cb; + on_stream_frame_recv_callback on_stream_frame_recv_cb; + on_reconnect_callback on_reconnect_cb; + on_disconnect_callback on_disconnect_cb; +} http2_stream_cb_t; + +typedef struct { + char *stream; /* point to stream data buffer */ + uint32_t stream_len; /* file content length */ + uint32_t send_len; /* data had sent length */ + uint32_t packet_len; /* one packet length */ + const char *identify; /* path string to identify a stream service */ + int h2_stream_id; /* stream identifier which is a field in HTTP2 frame */ + char *channel_id; /* string return by server to identify a specific stream channel, + different from stream identifier which is a field in HTTP2 frame */ + void *user_data; /* user data brought in at stream open */ +} stream_data_info_t; + +#ifdef FS_ENABLED +typedef enum { + UPLOAD_FILE_NOT_EXIST = -9, + UPLOAD_FILE_READ_FAILED = -8, + UPLOAD_STREAM_OPEN_FAILED = -7, + UPLOAD_STREAM_SEND_FAILED = -6, + UPLOAD_MALLOC_FAILED = -5, + UPLOAD_NULL_POINT = -2, + UPLOAD_ERROR_COMMON = -1, + UPLOAD_SUCCESS = 0, +} http2_file_upload_result_t; + +typedef void (* upload_file_result_cb)(const char *path, int result, void *user_data); +DLL_IOT_API int IOT_HTTP2_Stream_UploadFile(void *handle, const char *file_path, const char *identify, + header_ext_info_t *header, + upload_file_result_cb cb, void *user_data); +#endif +DLL_IOT_API void *IOT_HTTP2_Connect(device_conn_info_t *conn_info, http2_stream_cb_t *user_cb); +DLL_IOT_API int IOT_HTTP2_Stream_Open(void *handle, stream_data_info_t *info, header_ext_info_t *header); +DLL_IOT_API int IOT_HTTP2_Stream_Send(void *handle, stream_data_info_t *info, header_ext_info_t *header); +DLL_IOT_API int IOT_HTTP2_Stream_Query(void *handle, stream_data_info_t *info, header_ext_info_t *header); +DLL_IOT_API int IOT_HTTP2_Stream_Close(void *handle, stream_data_info_t *info); +DLL_IOT_API int IOT_HTTP2_Disconnect(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* IOT_EXPORT_FILE_UPLOADER_H */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_linkkit.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_linkkit.h new file mode 100755 index 000000000..eeaf737cf --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_linkkit.h @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_LINKKIT_H_ +#define _IOT_EXPORT_LINKKIT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "iot_export.h" + +#define PRODUCT_KEY_MAXLEN (20 + 1) +#define DEVICE_NAME_MAXLEN (32 + 1) +#define DEVICE_SECRET_MAXLEN (64 + 1) +#define PRODUCT_SECRET_MAXLEN (64 + 1) + +#ifdef DEVICE_MODEL_GATEWAY +typedef enum _gateway_subdev_event_e +{ + ITM_EVENT_TOPO_DELETE_REPLY, + ITM_EVENT_SUBDEV_RESET_REPLY, + ITM_EVENT_TOPO_ADD_REPLY, + ITM_EVENT_COMBINE_LOGIN_REPLY, + ITM_EVENT_COMBINE_LOGOUT_REPLY, + ITM_EVENT_COMBINE_BATCH_LOGIN_REPLY, + ITM_EVENT_COMBINE_BATCH_LOGOUT_REPLY +}gateway_subdev_event_e; +#endif + +typedef enum { + IOTX_LINKKIT_DEV_TYPE_MASTER, + IOTX_LINKKIT_DEV_TYPE_SLAVE, + IOTX_LINKKIT_DEV_TYPE_MAX +} iotx_linkkit_dev_type_t; + +typedef struct { + char product_key[PRODUCT_KEY_MAXLEN]; + char product_secret[PRODUCT_SECRET_MAXLEN]; + char device_name[DEVICE_NAME_MAXLEN]; + char device_secret[DEVICE_SECRET_MAXLEN]; +} iotx_linkkit_dev_meta_info_t; + +typedef enum { + /* post property value to cloud */ + ITM_MSG_POST_PROPERTY, + + /* post device info update message to cloud */ + ITM_MSG_DEVICEINFO_UPDATE, + + /* post device info delete message to cloud */ + ITM_MSG_DEVICEINFO_DELETE, + + /* post raw data to cloud */ + ITM_MSG_POST_RAW_DATA, + + /* only for slave device, send login request to cloud */ + ITM_MSG_LOGIN, + + /* only for slave device, send logout request to cloud */ + ITM_MSG_LOGOUT, + + /* only for slave device, send login request to cloud */ + ITM_MSG_BATCH_LOGIN, + + /* only for slave device, send logout request to cloud */ + ITM_MSG_BATCH_LOGOUT, + + /* only for slave device, send delete topo request to cloud */ + ITM_MSG_DELETE_TOPO, + + /* connect subdev use new way*/ + ITM_MSG_CONNECT_SUBDEV, + + /* query ntp time from cloud */ + ITM_MSG_QUERY_TIMESTAMP, + + /* only for master device, query topo list */ + ITM_MSG_QUERY_TOPOLIST, + + /* only for master device, request reset subdev */ + ITM_MSG_SUBDEV_RESET, + + /* only for master device, qurey subdev device id*/ + ITM_MSG_QUERY_SUBDEV_ID, + + /* only for master device, qurey firmware ota data */ + ITM_MSG_QUERY_FOTA_DATA, + + /* only for master device, qurey config ota data */ + ITM_MSG_QUERY_COTA_DATA, + + /* only for master device, request config ota data from cloud */ + ITM_MSG_REQUEST_COTA, + + /* only for master device, request fota image from cloud */ + ITM_MSG_REQUEST_FOTA_IMAGE, + + /* reply event notify to cloud */ + ITM_MSG_EVENT_NOTIFY_REPLY, + +#ifdef DM_UNIFIED_SERVICE_POST + /* post data to cloud and this this unify method*/ + ITM_MSG_UNIFIED_SERVICE_POST, +#endif + + IOTX_LINKKIT_MSG_MAX +} iotx_linkkit_msg_type_t; + +/** + * @brief create a new device + * + * @param dev_type. type of device which will be created. see iotx_linkkit_dev_type_t + * @param meta_info. The product key, product secret, device name and device secret of new device. + * + * @return success: device id (>=0), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info); + +/** + * @brief start device network connection. + * for master device, start to connect aliyun server. + * for slave device, send message to cloud for register new device and add topo with master device + * + * @param devid. device identifier. + * + * @return success: device id (>=0), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Connect(int devid); + +/** + * @brief try to receive message from cloud and dispatch these message to user event callback + * + * @param timeout_ms. timeout for waiting new message arrived + * + * @return void. + * + */ +DLL_IOT_API void IOT_Linkkit_Yield(int timeout_ms); + +/** + * @brief close device network connection and release resources. + * for master device, disconnect with aliyun server and release all local resources. + * for slave device, send message to cloud for delete topo with master device and unregister itself, then release device's resources. + * + * @param devid. device identifier. + * + * @return success: 0, fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Close(int devid); + + +/** + * @brief Report message to cloud + * + * @param devid. device identifier. + * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows: + * ITM_MSG_POST_PROPERTY + * ITM_MSG_DEVICEINFO_UPDATE + * ITM_MSG_DEVICEINFO_DELETE + * ITM_MSG_POST_RAW_DATA + * ITM_MSG_LOGIN + * ITM_MSG_LOGOUT + * + * @param payload. message payload. + * @param payload_len. message payload length. + * + * @return success: 0 or message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Report_Ext(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, + int payload_len, int sento); +/** + * @brief Report message to cloud + * + * @param devid. device identifier. + * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows: + * ITM_MSG_POST_PROPERTY + * ITM_MSG_DEVICEINFO_UPDATE + * ITM_MSG_DEVICEINFO_DELETE + * ITM_MSG_POST_RAW_DATA + * ITM_MSG_LOGIN + * ITM_MSG_LOGOUT + * + * @param payload. message payload. + * @param payload_len. message payload length. + * + * @return success: 0 or message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, + int payload_len); + +/** + * @brief post message to cloud + * + * @param devid. device identifier. + * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows: + * ITM_MSG_QUERY_TIMESTAMP + * ITM_MSG_QUERY_TOPOLIST + * ITM_MSG_QUERY_FOTA_DATA + * ITM_MSG_QUERY_COTA_DATA + * ITM_MSG_REQUEST_COTA + * ITM_MSG_REQUEST_FOTA_IMAGE + * + * @param payload. message payload. + * @param payload_len. message payload length. + * + * @return success: 0 or message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, + int payload_len); + +/** + * @brief post event to cloud + * + * @param devid. device identifier. + * @param eventid. tsl event id. + * @param eventid_len. length of tsl event id. + * @param payload. event payload. + * @param payload_len. event payload length. + * + * @return success: message id (>=1), fail: -1. + * + */ +DLL_IOT_API int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len); + +#ifdef LOG_REPORT_TO_CLOUD + int check_target_msg(const char *input, int len); + void get_msgid(char *payload, int is_cloud); + void send_permance_info(char *input, int input_len, char *comments, int report_format); +#endif + + + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_mqtt.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_mqtt.h new file mode 100755 index 000000000..69028120f --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_mqtt.h @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_MQTT_H_ +#define _IOT_EXPORT_MQTT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MUTLI_SUBSCIRBE_MAX (5) + +/* From mqtt_client.h */ +typedef enum { + IOTX_MQTT_QOS0 = 0, + IOTX_MQTT_QOS1, + IOTX_MQTT_QOS2, + IOTX_MQTT_QOS3_SUB_LOCAL +} iotx_mqtt_qos_t; + +typedef enum { + + /* Undefined event */ + IOTX_MQTT_EVENT_UNDEF = 0, + + /* MQTT disconnect event */ + IOTX_MQTT_EVENT_DISCONNECT = 1, + + /* MQTT reconnect event */ + IOTX_MQTT_EVENT_RECONNECT = 2, + + /* A ACK to the specific subscribe which specify by packet-id be received */ + IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS = 3, + + /* No ACK to the specific subscribe which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT = 4, + + /* A failed ACK to the specific subscribe which specify by packet-id be received*/ + IOTX_MQTT_EVENT_SUBCRIBE_NACK = 5, + + /* A ACK to the specific unsubscribe which specify by packet-id be received */ + IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6, + + /* No ACK to the specific unsubscribe which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7, + + /* A failed ACK to the specific unsubscribe which specify by packet-id be received*/ + IOTX_MQTT_EVENT_UNSUBCRIBE_NACK = 8, + + /* A ACK to the specific publish which specify by packet-id be received */ + IOTX_MQTT_EVENT_PUBLISH_SUCCESS = 9, + + /* No ACK to the specific publish which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_PUBLISH_TIMEOUT = 10, + + /* A failed ACK to the specific publish which specify by packet-id be received*/ + IOTX_MQTT_EVENT_PUBLISH_NACK = 11, + + /* MQTT packet published from MQTT remote broker be received */ + IOTX_MQTT_EVENT_PUBLISH_RECEIVED = 12, + + /* MQTT packet buffer overflow which the remaining space less than to receive byte */ + IOTX_MQTT_EVENT_BUFFER_OVERFLOW = 13, +} iotx_mqtt_event_type_t; + +/* topic information */ +typedef struct { + uint16_t packet_id; + uint8_t qos; + uint8_t dup; + uint8_t retain; + uint16_t topic_len; + uint32_t payload_len; + const char *ptopic; + const char *payload; +} iotx_mqtt_topic_info_t, *iotx_mqtt_topic_info_pt; + + +typedef struct { + + /* Specify the event type */ + iotx_mqtt_event_type_t event_type; + + /* + * Specify the detail event information. @msg means different to different event types: + * + * 1) IOTX_MQTT_EVENT_UNKNOWN, + * IOTX_MQTT_EVENT_DISCONNECT, + * IOTX_MQTT_EVENT_RECONNECT : + * Its data type is string and the value is detail information. + * + * 2) IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS, + * IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT, + * IOTX_MQTT_EVENT_SUBCRIBE_NACK, + * IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS, + * IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT, + * IOTX_MQTT_EVENT_UNSUBCRIBE_NACK + * IOTX_MQTT_EVENT_PUBLISH_SUCCESS, + * IOTX_MQTT_EVENT_PUBLISH_TIMEOUT, + * IOTX_MQTT_EVENT_PUBLISH_NACK : + * Its data type is @uint32_t and the value is MQTT packet identifier. + * + * 3) IOTX_MQTT_EVENT_PUBLISH_RECEIVED: + * Its data type is @iotx_mqtt_packet_info_t and see detail at the declare of this type. + * + * */ + void *msg; +} iotx_mqtt_event_msg_t, *iotx_mqtt_event_msg_pt; + + +/** + * @brief It define a datatype of function pointer. + * This type of function will be called when a related event occur. + * + * @param pcontext : The program context. + * @param pclient : The MQTT client. + * @param msg : The event message. + * + * @return none + */ +typedef void (*iotx_mqtt_event_handle_func_fpt)(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg); + + +/* The structure of MQTT event handle */ +typedef struct { + iotx_mqtt_event_handle_func_fpt h_fp; + void *pcontext; +} iotx_mqtt_event_handle_t, *iotx_mqtt_event_handle_pt; + + +/* The structure of MQTT initial parameter */ +typedef struct { + + uint16_t port; /* Specify MQTT broker port */ + const char *host; /* Specify MQTT broker host */ + const char *client_id; /* Specify MQTT connection client id*/ + const char *username; /* Specify MQTT user name */ + const char *password; /* Specify MQTT password */ + + /* Specify MQTT transport channel and key. + * If the value is NULL, it means that use TCP channel, + * If the value is NOT NULL, it means that use SSL/TLS channel and + * @pub_key point to the CA certification */ + const char *pub_key; + + uint8_t clean_session; /* Specify MQTT clean session or not*/ + uint32_t request_timeout_ms; /* Specify timeout of a MQTT request in millisecond */ + uint32_t keepalive_interval_ms; /* Specify MQTT keep-alive interval in millisecond */ + uint32_t write_buf_size; /* Specify size of write-buffer in byte */ + uint32_t read_buf_size; /* Specify size of read-buffer in byte */ + + iotx_mqtt_event_handle_t handle_event; /* Specify MQTT event handle */ + +} iotx_mqtt_param_t, *iotx_mqtt_param_pt; + +#ifdef MAL_ENABLED +#define IOT_MQTT_Construct MAL_MQTT_Construct +#define IOT_MQTT_Destroy MAL_MQTT_Destroy +#define IOT_MQTT_Yield MAL_MQTT_Yield +#define IOT_MQTT_CheckStateNormal MAL_MQTT_CheckStateNormal +#define IOT_MQTT_Subscribe_Sync MAL_MQTT_Subscribe_Sync +#define IOT_MQTT_Subscribe MAL_MQTT_Subscribe +#define IOT_MQTT_Unsubscribe MAL_MQTT_Unsubscribe +#define IOT_MQTT_Publish MAL_MQTT_Publish +#define IOT_MQTT_Publish_Simple MAL_MQTT_Publish_Simple + +DLL_IOT_API void *MAL_MQTT_Construct(iotx_mqtt_param_t *pInitParams); +DLL_IOT_API int MAL_MQTT_Destroy(void **phandle); +DLL_IOT_API int MAL_MQTT_Yield(void *handle, int timeout_ms); +DLL_IOT_API int MAL_MQTT_Subscribe(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext); +DLL_IOT_API int MAL_MQTT_Subscribe_Sync(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms); +DLL_IOT_API int MAL_MQTT_Unsubscribe(void *handle, const char *topic_filter); +DLL_IOT_API int MAL_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg); +DLL_IOT_API int MAL_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len); +#else /* MAL_ENABLED */ +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_mqtt mqtt + * @{ + */ + +/** + * @brief Construct the MQTT client + * This function initialize the data structures, establish MQTT connection. + * + * @param [in] pInitParams: specify the MQTT client parameter. + * + * @retval NULL : Construct failed. + * @retval NOT_NULL : The handle of MQTT client. + * @see None. + */ +DLL_IOT_API void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams); + + +/** + * @brief Deconstruct the MQTT client + * This function disconnect MQTT connection and release the related resource. + * + * @param [in] phandle: pointer of handle, specify the MQTT client. + * + * @retval 0 : Deconstruct success. + * @retval -1 : Deconstruct failed. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Destroy(void **phandle); + + +/** + * @brief Handle MQTT packet from remote server and process timeout request + * which include the MQTT subscribe, unsubscribe, publish(QOS >= 1), reconnect, etc.. + * + * @param [in] handle: specify the MQTT client. + * @param [in] timeout_ms: specify the timeout in millisecond in this loop. + * + * @return status. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Yield(void *handle, int timeout_ms); + + +/** + * @brief Post log information to cloud. + * + * @param [in] handle: specify the MQTT client. + * @param [in] levle: log level string + * @param [in] moduel: module string. + * @param [in] msg: log information string. + * + * @retval 0 : Post successful. + * @retval -1 : Post fail. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_LogPost(void *pHandle, const char *level, const char *module, const char *msg); + +/** + * @brief check whether MQTT connection is established or not. + * + * @param [in] handle: specify the MQTT client. + * + * @retval true : MQTT in normal state. + * @retval false : MQTT in abnormal state. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_CheckStateNormal(void *handle); + + +/** + * @brief Subscribe MQTT topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] topic_handle_func: specify the topic handle callback-function. + * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back. + * + * @retval -1 : Subscribe failed. + * @retval >=0 : Subscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Subscribe(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext); + +/** + * @brief Subscribe MQTT topic and wait suback. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] topic_handle_func: specify the topic handle callback-function. + * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back. + * @param [in] timeout_ms: time in ms to wait. + * + * @retval -1 : Subscribe failed. + * @retval >=0 : Subscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Subscribe_Sync(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms); + + +/** + * @brief Unsubscribe MQTT topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * + * @retval -1 : Unsubscribe failed. + * @retval >=0 : Unsubscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter); + + +/** + * @brief Publish message to specific topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_name: specify the topic name. + * @param [in] topic_msg: specify the topic message. + * + * @retval -1 : Publish failed. + * @retval 0 : Publish successful, where QoS is 0. + * @retval >0 : Publish successful, where QoS is >= 0. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg); +/** + * @brief Publish message to specific topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_name: specify the topic name. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] data: specify the topic message payload. + * @param [in] len: specify the topic message payload len. + * + * @retval -1 : Publish failed. + * @retval 0 : Publish successful, where QoS is 0. + * @retval >0 : Publish successful, where QoS is >= 0. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +DLL_IOT_API int IOT_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len); +/* From mqtt_client.h */ +/** @} */ /* end of api_mqtt */ + +/** @} */ /* end of api */ +#endif /* MAL_ENABLED */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ota.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ota.h new file mode 100755 index 000000000..703d3301f --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ota.h @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __OTA_EXPORT_H__ +#define __OTA_EXPORT_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "iot_import.h" + +#define OTA_CH_SIGNAL_MQTT (0) +#define OTA_CH_SIGNAL_COAP (1) +#define OTA_CH_FETCH_HTTP (1) + + +typedef enum { + + IOT_OTAE_GENERAL = -1, + IOT_OTAE_INVALID_PARAM = -2, + IOT_OTAE_INVALID_STATE = -3, + IOT_OTAE_STR_TOO_LONG = -4, + IOT_OTAE_FETCH_FAILED = -5, + IOT_OTAE_NOMEM = -6, + IOT_OTAE_OSC_FAILED = -7, + IOT_OTAE_NONE = 0, + +} IOT_OTA_Err_t; + + +/* State of OTA */ +typedef enum { + IOT_OTAS_UNINITED = 0, /* Uninitialized State */ + IOT_OTAS_INITED, /* Initialized State */ + IOT_OTAS_FETCHING, /* Fetching firmware */ + IOT_OTAS_FETCHED /* Fetching firmware finish */ +} IOT_OTA_State_t; + +typedef enum { + IOT_OTAT_NONE, + IOT_OTAT_COTA, + IOT_OTAT_FOTA, + IOT_OTAT_FOTA_OFFLINE +} IOT_OTA_Type_t; + +/* Progress of OTA */ +typedef enum { + + /* Burn firmware file failed */ + IOT_OTAP_BURN_FAILED = -4, + + /* Check firmware file failed */ + IOT_OTAP_CHECK_FALIED = -3, + + /* Fetch firmware file failed */ + IOT_OTAP_FETCH_FAILED = -2, + + /* Initialized failed */ + IOT_OTAP_GENERAL_FAILED = -1, + + + /* [0, 100], percentage of fetch progress */ + + /* The minimum percentage of fetch progress */ + IOT_OTAP_FETCH_PERCENTAGE_MIN = 0, + + /* The maximum percentage of fetch progress */ + IOT_OTAP_FETCH_PERCENTAGE_MAX = 100 + +} IOT_OTA_Progress_t; + + +typedef enum { + IOT_OTAG_COTA_CONFIG_ID, + IOT_OTAG_COTA_CONFIG_SIZE, + IOT_OTAG_COTA_SIGN, + IOT_OTAG_COTA_SIGN_METHOD, + IOT_OTAG_COTA_URL, + IOT_OTAG_COTA_GETTYPE, + IOT_OTAG_OTA_TYPE, + IOT_OTAG_FETCHED_SIZE, /* option for get already fetched size */ + IOT_OTAG_FILE_SIZE, /* size of file */ + IOT_OTAG_MD5SUM, /* md5 in string format */ + IOT_OTAG_VERSION, /* version in string format */ + IOT_OTAG_CHECK_FIRMWARE, /* Check firmware is valid or not */ + IOT_OTAG_CHECK_CONFIG, /* Check config file is valid or not */ + IOT_OTAG_RESET_FETCHED_SIZE /* reset the size_fetched parameter to be 0 */ +} IOT_OTA_CmdType_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_ota ota + * @{ + */ + +/** + * @brief Initialize OTA module, and return handle. + * The MQTT client must be construct before calling this interface. + * + * @param [in] product_key: specify the product key. + * @param [in] device_name: specify the device name. + * @param [in] ch_signal: specify the signal channel. + * + * @retval 0 : Successful. + * @retval -1 : Failed. + * @see None. + */ +DLL_IOT_API void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal); + + +/** + * @brief Deinitialize OTA module specified by the 'handle', and release the related resource. + * You must call this interface to release resource if reboot is not invoked after downloading. + * + * @param [in] handle: specify the OTA module. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_Deinit(void *handle); + + +/** + * @brief Report firmware version information to OTA server (optional). + * NOTE: please + * + * @param [in] handle: specify the OTA module. + * @param [in] version: specify the firmware version in string format. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_ReportVersion(void *handle, const char *version); + +/** + * @brief Report detail progress to OTA server (optional). + * NOTE: please + * + * @param [in] handle: specify the OTA module. + * @param [in] progress: specify the progress defined by 'IOT_OTA_Progress_t'. + * @param [in] msg: detail progress information in string. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg); + + +/** + * @brief Check whether is on fetching state + * + * @param [in] handle: specify the OTA module. + * + * @retval 1 : Yes. + * @retval 0 : No. + * @see None. + */ +DLL_IOT_API int IOT_OTA_IsFetching(void *handle); + + +/** + * @brief Check whether is on end-of-fetch state. + * + * @param [in] handle: specify the OTA module. + * + * @retval 1 : Yes. + * @retval 0 : False. + * @see None. + */ +DLL_IOT_API int IOT_OTA_IsFetchFinish(void *handle); + + +/** + * @brief fetch firmware from remote server with specific timeout value. + * NOTE: If you want to download more faster, the bigger 'buf' should be given. + * + * @param [in] handle: specify the OTA module. + * @param [out] buf: specify the space for storing firmware data. + * @param [in] buf_len: specify the length of 'buf' in bytes. + * @param [in] timeout_s: specify the timeout value in second. + * + * @retval < 0 : Error occur.. + * @retval 0 : No any data be downloaded in 'timeout_s' timeout period. + * @retval (0, len] : The length of data be downloaded in 'timeout_s' timeout period in bytes. + * @see None. + */ +DLL_IOT_API int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s); + + +/** + * @brief Get OTA information specified by 'type'. + * By this interface, you can get information like state, size of file, md5 of file, etc. + * + * @param [in] handle: handle of the specific OTA + * @param [in] type: specify what information you want, see detail 'IOT_OTA_CmdType_t' + * @param [out] buf: specify buffer for data exchange + * @param [in] buf_len: specify the length of 'buf' in byte. + * @return + @verbatim + NOTE: + 1) When type is IOT_OTAG_FETCHED_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 2) When type is IOT_OTAG_FILE_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 3) When type is IOT_OTAG_MD5SUM, 'buf' should be a buffer, and 'buf_len' should be 33. + 4) When type is IOT_OTAG_VERSION, 'buf' should be a buffer, and 'buf_len' should be OTA_VERSION_LEN_MAX. + 5) When type is IOT_OTAG_CHECK_FIRMWARE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 0, firmware is invalid; 1, firmware is valid. + @endverbatim + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, size_t buf_len); + + +/** + * @brief Get last error code. + * + * @param [in] handle: specify the OTA module. + * + * @return The error code. + * @see None. + */ +DLL_IOT_API int IOT_OTA_GetLastError(void *handle); + +/** @} */ /* end of api_ota */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif + +#endif /* __OTA_EXPORT_H__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_reset.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_reset.h new file mode 100755 index 000000000..b7dd29189 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_reset.h @@ -0,0 +1,8 @@ +#ifndef __IOT_EXPORT_RESET_H__ +#define __IOT_EXPORT_RESET_H__ + +extern int iotx_sdk_reset_local(void); +extern int iotx_sdk_reset_cloud(iotx_vendor_dev_reset_type_t *reset_type); +extern int iotx_sdk_reset(iotx_vendor_dev_reset_type_t *reset_type); + +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_shadow.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_shadow.h new file mode 100755 index 000000000..a2551973d --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_shadow.h @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __SHADOW_EXPORT_H__ +#define __SHADOW_EXPORT_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* From shadow.h */ +#include +typedef enum { + IOTX_SHADOW_ACK_TIMEOUT = -1, + IOTX_SHADOW_ACK_NONE = 0, + IOTX_SHADOW_ACK_SUCCESS = 200, + IOTX_SHADOW_ACK_ERR_JSON_FMT_IS_INVALID = 400, + IOTX_SHADOW_ACK_ERR_METHOD_IS_NULL = 401, + IOTX_SHADOW_ACK_ERR_STATE_IS_NULL = 402, + IOTX_SHADOW_ACK_ERR_VERSION_IS_INVALID = 403, + IOTX_SHADOW_ACK_ERR_REPORTED_IS_NULL = 404, + IOTX_SHADOW_ACK_ERR_REPORTED_ATTRIBUTE_IS_NULL = 405, + IOTX_SHADOW_ACK_ERR_METHOD_IS_INVALID = 406, + IOTX_SHADOW_ACK_ERR_SHADOW_DOCUMENT_IS_NULL = 407, + IOTX_SHADOW_ACK_ERR_ATTRIBUTE_EXCEEDED = 408, + IOTX_SHADOW_ACK_ERR_SERVER_FAILED = 500, +} iotx_shadow_ack_code_t; + +typedef enum { + IOTX_SHADOW_READONLY, + IOTX_SHADOW_WRITEONLY, + IOTX_SHADOW_RW +} iotx_shadow_datamode_t; + +typedef enum { + IOTX_SHADOW_NULL, + IOTX_SHADOW_INT32, + IOTX_SHADOW_STRING, +} iotx_shadow_attr_datatype_t; + +typedef struct { + int flag_new; + uint32_t buf_size; + uint32_t offset; + char *buf; +} format_data_t, *format_data_pt; + +typedef struct { + uint32_t base_system_time; /* in millisecond */ + uint32_t epoch_time; +} iotx_shadow_time_t, *iotx_shadow_time_pt; + +typedef void (*iotx_push_cb_fpt)( + void *pcontext, + int ack_code, + const char *ack_msg, /* NOTE: NOT a string. */ + uint32_t ack_msg_len); + +struct iotx_shadow_attr_st; + +typedef void (*iotx_shadow_attr_cb_t)(struct iotx_shadow_attr_st *pattr); + +typedef enum{ + SHADOW_DOWNSTREAM_METHOD_IGNORE, + SHADOW_DOWNSTREAM_METHOD_CONTROL, + SHADOW_DOWNSTREAM_METHOD_REPLY, +}shadow_downstream_method_type; + +typedef struct iotx_shadow_attr_st { + iotx_shadow_datamode_t mode; /* data mode */ + const char *pattr_name; /* attribute name */ + void *pattr_data; /* pointer to the attribute data */ + iotx_shadow_attr_datatype_t attr_type; /* data type */ + uint32_t timestamp; /* timestamp in Epoch(Unix) format */ + iotx_shadow_attr_cb_t callback; /* callback when related control message come. */ + char flag_update; + shadow_downstream_method_type method_type; +} iotx_shadow_attr_t, *iotx_shadow_attr_pt; + +typedef struct { + iotx_mqtt_param_t mqtt; +} iotx_shadow_para_t, *iotx_shadow_para_pt; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_shadow shadow + * @{ + */ + +/** + * @brief Construct the Device Shadow. + * This function initialize the data structures, establish MQTT connection. + * and subscribe the topic: "/shadow/get/${product_key}/${device_name}". + * + * @param [in] pparam: The specific initial parameter. + * @retval NULL : Construct shadow failed. + * @retval NOT_NULL : Construct success. + * @see None. + */ +DLL_IOT_API void *IOT_Shadow_Construct(iotx_shadow_para_pt pparam); + +/** + * @brief Deconstruct the specific device shadow. + * + * @param [in] handle: The handle of device shaodw. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_Destroy(void *handle); + +/** + * @brief Handle MQTT packet from cloud and wait list. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] timeout_ms: Specify the timeout value in millisecond. In other words, the API block 'timeout'_ms millisecond maximumly. + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_Shadow_Yield(void *handle, uint32_t timeout_ms); + +/** + * @brief Create a data type registered to the server. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pattr: The parameter which registered to the server. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_RegisterAttribute(void *handle, iotx_shadow_attr_pt pattr); + +/** + * @brief Delete the specific attribute. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pattr: The parameter to be deleted from server. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_DeleteAttribute(void *handle, iotx_shadow_attr_pt pattr); + +/** + * @brief Start a process the structure of the data type format. + * + * @param [in] handle: The handle of device shaodw. + * @param [out] pformat: The format struct of device shadow. + * @param [in] buf: The buf which store device shadow. + * @param [in] size: Maximum length of device shadow attribute. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_PushFormat_Init( + void *handle, + format_data_pt pformat, + char *buf, + uint16_t size); + +/** + * @brief Format the attribute name and value for update. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pformat: The format struct of device shadow. + * @param [in] pattr: To have created the data type of the format in the add member attributes. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_PushFormat_Add( + void *handle, + format_data_pt pformat, + iotx_shadow_attr_pt pattr); + +/** + * @brief Complete a process the structure of the data type format. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] pformat: The format struct of device shadow. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_PushFormat_Finalize(void *handle, format_data_pt pformat); + +/** + * @brief Update data to Cloud. It is a synchronous interface. + * + * @param [in] handle: The handle of device shaodw. + * @param [in] data: The buf which synchronization with the server. + * @param [in] data_len: The length, in bytes, of the data pointed to by the data parameter. + * @param [in] timeout_s: The timeout_s in second.In other word,the API will block timeout_s second. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_Push( + void *handle, + char *data, + uint32_t data_len, + uint16_t timeout_s); + +/** + * @brief Update data to Cloud. It is a asynchronous interface. + * The result of this update will be informed by calling the callback function cb_fpt. + * @param [in] handle: The handle of device shadow. + * @param [in] data: The buf which synchronization with the server. + * @param [in] data_len: The length, in bytes, of the data pointed to by the data parameter. + * @param [in] timeout_s: Specify the timeout value in second. Shadow will timeout after 'timeout_s' second if did not receive push response. + * @param [in] cb_fpt: Specify the callback function which recieve ack_code from server after push device shadow. + * @param [in] pcontext: Specify the context which passed to the callback function. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +DLL_IOT_API int IOT_Shadow_Push_Async( + void *handle, + char *data, + unsigned int data_len, + uint16_t timeout_s, + iotx_push_cb_fpt cb_fpt, + void *pcontext); + +/** + * @brief Synchronize device shadow data from cloud. + * It is a synchronous interface. + * @param [in] handle: The handle of device shaodw. + * @retval SUCCESS_RETURN : Success. + * @retval other : See iotx_err_t. + * @see None. + */ +iotx_err_t IOT_Shadow_Pull(void *handle); + +/* From shadow.h */ + +/** @} */ /* end of api_shadow */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif +#endif /* __SHADOW_EXPORT_H__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_state.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_state.h new file mode 100755 index 000000000..b55665d51 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_state.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#ifndef __IOT_EXPORTS_STATE_H__ +#define __IOT_EXPORTS_STATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define STATE_BASE (0x0000) + +/* General: 0x0000 ~ 0x00FF */ +#define STATE_SUCCESS (STATE_BASE - 0x0000) + +/* General: 0x0000 ~ 0x00FF */ + +/* User Input: 0x0100 ~ 0x01FF */ +#define STATE_USER_INPUT_BASE (-0x0100) +#define STATE_USER_INPUT_NULL_POINTER (STATE_USER_INPUT_BASE - 0x0001) +#define STATE_USER_INPUT_OUT_RANGE (STATE_USER_INPUT_BASE - 0x0002) + +/* User Input: 0x0100 ~ 0x01FF */ + +/* System: 0x0200 ~ 0x02FF */ +#define STATE_SYS_DEPEND_BASE (-0x0200) +#define STATE_SYS_DEPEND_MALLOC (STATE_SYS_DEPEND_BASE - 0x0001) +#define STATE_SYS_DEPEND_KV_GET (STATE_SYS_DEPEND_BASE - 0x0002) +#define STATE_SYS_DEPEND_KV_SET (STATE_SYS_DEPEND_BASE - 0x0003) +#define STATE_SYS_DEPEND_KV_DELETE (STATE_SYS_DEPEND_BASE - 0x0004) +#define STATE_SYS_DEPEND_TIMER_CREATE (STATE_SYS_DEPEND_BASE - 0x0005) +#define STATE_SYS_DEPEND_TIMER_START (STATE_SYS_DEPEND_BASE - 0x0006) +#define STATE_SYS_DEPEND_TIMER_STOP (STATE_SYS_DEPEND_BASE - 0x0007) +#define STATE_SYS_DEPEND_TIMER_DELETE (STATE_SYS_DEPEND_BASE - 0x0008) +#define STATE_SYS_DEPEND_MUTEX_CREATE (STATE_SYS_DEPEND_BASE - 0x0009) +#define STATE_SYS_DEPEND_MUTEX_LOCK (STATE_SYS_DEPEND_BASE - 0x000A) +#define STATE_SYS_DEPEND_MUTEX_UNLOCK (STATE_SYS_DEPEND_BASE - 0x000B) +#define STATE_SYS_DEPEND_NWK_CLOSE (STATE_SYS_DEPEND_BASE - 0x000C) +#define STATE_SYS_DEPEND_NWK_TIMEOUT (STATE_SYS_DEPEND_BASE - 0x000D) +#define STATE_SYS_DEPEND_NWK_INVALID_HANDLE (STATE_SYS_DEPEND_BASE - 0x000E) + +/* System: 0x0200 ~ 0x02FF */ + +/* MQTT: 0x0300 ~ 0x03FF */ +#define STATE_MQTT_BASE (-0x0300) + +/* Deserialized CONNACK from MQTT server says protocol version is unacceptable */ +#define STATE_MQTT_CONNACK_VERSION_UNACCEPT (STATE_MQTT_BASE - 0x0001) +/* Deserialized CONNACK from MQTT server says identifier is rejected */ +#define STATE_MQTT_CONNACK_IDENT_REJECT (STATE_MQTT_BASE - 0x0002) +/* Deserialized CONNACK from MQTT server says service is not available */ +#define STATE_MQTT_CONNACK_SERVICE_NA (STATE_MQTT_BASE - 0x0003) +/* Deserialized CONNACK from MQTT server says it failed to authorize */ +#define STATE_MQTT_CONNACK_NOT_AUTHORIZED (STATE_MQTT_BASE - 0x0004) +/* Deserialized CONNACK from MQTT server says username/password is invalid */ +#define STATE_MQTT_CONNACK_BAD_USERDATA (STATE_MQTT_BASE - 0x0005) + +/* MQTT: 0x0300 ~ 0x03FF */ + +/* WiFi Provision: 0x0400 ~ 0x04FF */ +#define STATE_WIFI_BASE (-0x0400) + +/* WiFi Provision: 0x0400 ~ 0x04FF */ + +/* COAP: 0x0500 ~ 0x05FF */ +#define STATE_COAP_BASE (-0x0500) + +/* COAP: 0x0500 ~ 0x05FF */ + +/* HTTP: 0x0600 ~ 0x06FF */ +#define STATE_HTTP_BASE (-0x0600) + +/* HTTP: 0x0600 ~ 0x06FF */ + +/* OTA: 0x0700 ~ 0x07FF */ +#define STATE_OTA_BASE (-0x0700) + +/* OTA: 0x0700 ~ 0x07FF */ + +/* Bind: 0x0800 ~ 0x08FF */ +#define STATE_BIND_BASE (-0x0800) +#define STATE_BIND_SET_APP_TOKEN (STATE_BIND_BASE - 0x0001) +#define STATE_BIND_ALREADY_RESET (STATE_BIND_BASE - 0x0002) +#define STATE_BIND_REPORT_TOKEN (STATE_BIND_BASE - 0x0003) +#define STATE_BIND_REPORT_TOKEN_TIMEOUT (STATE_BIND_BASE - 0x0004) +#define STATE_BIND_REPORT_TOKEN_SUCCESS (STATE_BIND_BASE - 0x0005) +#define STATE_BIND_COAP_INIT_FAIL (STATE_BIND_BASE - 0x0006) +#define STATE_BIND_NOTIFY_TOKEN_SENT (STATE_BIND_BASE - 0x0007) +#define STATE_BIND_RECV_TOKEN_QUERY (STATE_BIND_BASE - 0x0008) +#define STATE_BIND_SENT_TOKEN_RESP (STATE_BIND_BASE - 0x0009) +#define STATE_BIND_RST_IN_PROGRESS (STATE_BIND_BASE - 0x000A) +#define STATE_BIND_MQTT_MSG_INVALID (STATE_BIND_BASE - 0x000B) +#define STATE_BIND_COAP_MSG_INVALID (STATE_BIND_BASE - 0x000C) + + +/* Bind: 0x0800 ~ 0x08FF */ + +/* Device Model: 0x0900 ~ 0x09FF */ +#define STATE_DEV_MODEL_BASE (-0x0900) + +/* Device Model: 0x0900 ~ 0x09FF */ + +/* SubDevice Mgmt: 0x0A00 ~ 0x0AFF */ +#define STATE_SUB_DEVICE_BASE (-0x0A00) + +/* SubDevice Mgmt: 0x0A00 ~ 0x0AFF */ + +#ifdef __cplusplus +} +#endif +#endif /* __IOT_EXPORTS_STATE_H__ */ + diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ticknotify.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ticknotify.h new file mode 100755 index 000000000..931f0c4b3 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_ticknotify.h @@ -0,0 +1,10 @@ +#ifndef _TICK_NOTIFY_H +#define _TICK_NOTIFY_H 1 + +#include "stdint.h" + +void *iotx_tick_notify_init(); +int iotx_tick_notify_deinit(); +int iotx_get_notify_time(uint64_t *tick); + +#endif \ No newline at end of file diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_timer.h b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_timer.h new file mode 100755 index 000000000..eead2bc8a --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/iot_export_timer.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_EXPORT_TIMER_H__ +#define __IOT_EXPORT_TIMER_H__ + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" { +#endif +#ifdef AIOT_DEVICE_TIMER_ENABLE +#include "iotx_log.h" + + #define DEVICETIMER "DeviceTimer" + #define DeviceTimerSize 13 + + #define DS "dev_timer" + #define DS_ERR(...) log_err(TS, __VA_ARGS__) + #define DS_WRN(...) log_warning(TS, __VA_ARGS__) + #define DS_INFO(...) log_info(TS, __VA_ARGS__) + #define DS_DEBUG(...) log_debug(TS, __VA_ARGS__) + typedef void (*devicetimer_callback)(const char *report_data, const char *property_name, const char *data); + int aiot_device_timer_init(const char **devicetimer_list, uint8_t num_devicetimer_list, devicetimer_callback timer_service_cb); + int deviceTimerParse(const char *input, uint8_t src, int save); + int aiot_device_timer_inited(void); + int aiot_device_timer_clear(void); +#else +#define NUM_OF_CONTROL_TARGETS 30 +#define NUM_OF_TARGETS_FLOAT 10 +#define NUM_OF_TARGETS_STRING 3 +#define NUM_OF_TSL_TYPES 3 /* 1:int/enum/bool; 2:float/double; 3:text/date */ + +#define STRING_MAX_LEN 80 +#define DAYS_OF_WEEK 7 +// #define ENABLE_LED_HSV +// #define ENABLE_LED_RGB +// #define ENABLE_LED_HSL + +void timer_service_clear(void); + +typedef void (*callback_fun)(const char *report_data, const char *property_name, int i_value, + double d_value, const char * s_value, int prop_idx); +typedef void (*callback_ntp_fun)(); + +int timer_service_init(const char **control_list, uint8_t num_control_list, + const char **countdownlist_target, uint8_t num_countdownlist_target, + const char **localtimer_list, uint8_t num_localtimer_list, + callback_fun timer_service_cb, int *num_of_tsl_type, callback_ntp_fun timer_ntp_cb); +int timer_service_property_set(const char* data); +char *timer_service_property_get(const char *request); + +#endif + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif + +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/linkkit_export.h b/code/application/source/sf_app/component/liveMng/inc/exports/linkkit_export.h new file mode 100755 index 000000000..e5e18c637 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/linkkit_export.h @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef LINKKIT_EXPORT_H +#define LINKKIT_EXPORT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +typedef void (*handle_post_cb_fp_t)(const void *thing_id, int respons_id, int code, const char *response_message, + void *ctx); +typedef void (*handle_subdev_cb_fp_t)(const void *thing_id, int code, const char *response_message, int success, + void *ctx); + +typedef struct _linkkit_ops { +#ifdef LOCAL_CONN_ENABLE + int (*on_connect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */ + int (*on_disconnect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */ +#else + int (*on_connect)(void *ctx); /* true: cloud connection; false: local connection */ + int (*on_disconnect)(void *ctx); /* true: cloud connection; false: local connection */ +#endif + int (*raw_data_arrived)(const void *thing_id, const void *data, int len, void *ctx); + int (*thing_create)(const void *thing_id, void *ctx); + int (*thing_enable)(const void *thing_id, void *ctx); + int (*thing_disable)(const void *thing_id, void *ctx); + int (*thing_call_service)(const void *thing_id, const char *service, int request_id, void *ctx); + int (*thing_prop_changed)(const void *thing_id, const char *property, void *ctx); + int (*linkit_data_arrived)(const void *thing_id, const void *data, int len, void *ctx); +} linkkit_ops_t; + +typedef enum _linkkit_loglevel { + linkkit_loglevel_emerg = 0, + linkkit_loglevel_crit, + linkkit_loglevel_error, + linkkit_loglevel_warning, + linkkit_loglevel_info, + linkkit_loglevel_debug, +} linkkit_loglevel_t; + +/* domain type */ +/* please sync with dm_cloud_domain_type_t */ +typedef enum { + /* shanghai */ + linkkit_cloud_domain_shanghai, + /* singapore */ + linkkit_cloud_domain_singapore, + /* japan */ + linkkit_cloud_domain_japan, + /* america */ + linkkit_cloud_domain_america, + /* germany */ + linkkit_cloud_domain_germany, + + linkkit_cloud_domain_max, +} linkkit_cloud_domain_type_t; + +/* device info related operation */ +typedef enum { + linkkit_extended_info_operate_update, + linkkit_extended_info_operate_delete, + + linkkit_deviceinfo_operate_max, +} linkkit_extended_info_operate_t; + +/** + * @brief dispatch message of queue for further process. + * + * @return void* + */ +DLL_IOT_API void *linkkit_dispatch(void); + +typedef enum { + linkkit_opt_property_post_reply, /* data type: int */ + linkkit_opt_event_post_reply, /* data type: int */ + linkkit_opt_property_set_reply /* data type: int */ +} linkkit_opt_t; + +/** + * @brief get leave signal. + * + * + * @return int,0 no leave signal, 1 get a leave signal + */ +DLL_IOT_API int being_deprecated linkkit_is_try_leave(); + +/** + * @brief start linkkit routines, and install callback funstions(async type for cloud connecting). + * + * @param opt, specify the option need to be set. + * @param data, specify the option value. + * + * @return int, 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_set_opt(linkkit_opt_t opt, void *data); + +/** + * @brief start linkkit routines, and install callback funstions(async type for cloud connecting). + * + * @param max_buffered_msg, specify max buffered message size. + * @param ops, callback function struct to be installed. + * @param get_tsl_from_cloud, config if device need to get tsl from cloud(!0) or local(0), if local selected, must invoke linkkit_set_tsl to tell tsl to dm after start complete. + * @param log_level, config log level. + * @param user_context, user context pointer. + * @param domain_type, specify the could server domain. + * + * @return int, 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_start(int max_buffered_msg, int get_tsl_from_cloud, + linkkit_loglevel_t log_level, + linkkit_ops_t *ops, + linkkit_cloud_domain_type_t domain_type, void *user_context); + +/** + * @brief stop linkkit routines. + * + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_end(void); + +/** + * @brief install user tsl. + * + * @param tsl, tsl string that contains json description for thing object. + * @param tsl_len, tsl string length. + * + * @return pointer to thing object, NULL when fails. + */ +DLL_IOT_API void *linkkit_set_tsl(const char *tsl, int tsl_len); + +/* patterns: */ +/* method: + * set_property_/event_output_/service_output_value: + * method_set, thing_id, identifier, value */ + +typedef enum { + linkkit_method_set_property_value = 0, + linkkit_method_set_event_output_value, + linkkit_method_set_service_output_value, + + linkkit_method_set_number, +} linkkit_method_set_t; + +/** + * @brief set value to property, event output, service output items. + * if identifier is struct type or service output type or event output type, use '.' as delimeter like "identifier1.ientifier2" + * to point to specific item. + * value and value_str could not be NULL at the same time; + * if value and value_str both as not NULL, value shall be used and value_str will be ignored. + * if value is NULL, value_str not NULL, value_str will be used. + * in brief, value will be used if not NULL, value_str will be used only if value is NULL. + * + * @param method_set, specify set value type. + * @param thing_id, pointer to thing object, specify which thing to set. + * @param identifier, property, event output, service output identifier. + * @param value. The value to be set, data type decided by data type of property as follows: + * int: int*, float: float*, double: double*, + * text: char*, enum: int*, date: char*, bool: int* + * + * @param value_str, value to set in string format if value is null. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_set_value(linkkit_method_set_t method_set, const void *thing_id, + const char *identifier, + const void *value, const char *value_str); + +typedef enum { + linkkit_method_get_property_value = 0, + linkkit_method_get_event_output_value, + linkkit_method_get_service_input_value, + linkkit_method_get_service_output_value, + + linkkit_method_get_number, +} linkkit_method_get_t; + +/** + * @brief get value from property, event output, service input/output items. + * if identifier is struct type or service input/output type or event output type, use '.' as delimeter like "identifier1.ientifier2" + * to point to specific item. + * value and value_str could not be NULL at the same time; + * if value and value_str both as not NULL, value shall be used and value_str will be ignored. + * if value is NULL, value_str not NULL, value_str will be used. + * in brief, value will be used if not NULL, value_str will be used only if value is NULL. + * @param method_get, specify get value type. + * @param thing_id, pointer to thing object, specify which thing to get. + * @param identifier, property, event output, service input/output identifier. + * @param value. The variable to store value, data type decided by data type of property as follows: + * int: int*, float: float*, double: double*, + * text: char**, enum: int*, date: char**, bool: int* + * + * @param value_str, value to get in string format. If success, memory of *value_str will be allocated, + * user should free the memory. + * + * @warning if data type is text or date, *value well be end with '\0'. + * the memory allocated to *value must be free by user. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_get_value(linkkit_method_get_t method_get, const void *thing_id, + const char *identifier, + void *value, char **value_str); + + +/** + * @brief answer to a service when a service requested by cloud. + * + * @param thing_id, pointer to thing object. + * @param service_identifier, service identifier to answer, user should get this identifier from handle_dm_callback_fp_t type callback + * report that "dm_callback_type_service_requested" happened, use this function to generate response to the service sender. + * @param response_id, id value in response payload. its value is from "dm_callback_type_service_requested" type callback function. + * use the same id as the request to send response as the same communication session. + * @param code, code value in response payload. for example, 200 when service successfully executed, 400 when not successfully executed. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_answer_service(const void *thing_id, const char *service_identifier, + int response_id, int code); + +/** + * @brief answer a down raw service when a raw service requested by cloud, or invoke a up raw service to cloud. + * + * @param thing_id, pointer to thing object. + * @param is_up_raw, specify up raw(not 0) or down raw reply(0). + * @param raw_data, raw data that sent to cloud. + * @param raw_data_length, raw data length that sent to cloud. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_raw_service(const void *thing_id, int is_up_raw, void *raw_data, + int raw_data_length); + +/** + * @brief trigger extended info update procedure. + * + * @param thing_id, pointer to thing object. + * @param params, json type string that user to send to cloud. + * @param linkkit_extended_info_operation, specify update type or delete type. + * + * @return 0 when success, -1 when fail. + */ + +DLL_IOT_API int being_deprecated linkkit_trigger_extended_info_operate(const void *thing_id, const char *params, + linkkit_extended_info_operate_t linkkit_extended_info_operation); + +/** + * @brief trigger a event to post to cloud. + * + * @param thing_id, pointer to thing object. + * @param event_identifier, event identifier to trigger. + * @param cb, callback function of event post. + * + * @return >=0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_trigger_event(const void *thing_id, const char *event_identifier, + handle_post_cb_fp_t cb); + +/** + * @brief post property to cloud. + * + * @param thing_id, pointer to thing object. + * @param property_identifier, used when trigger event with method "event.property.post", if set, post specified property, if NULL, post all. + * @param cb, callback function of property post. + * + * @return >=0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_post_property(const void *thing_id, const char *property_identifier, + handle_post_cb_fp_t cb); + +/** + * @brief this function used to yield when want to receive or send data. + * if multi-thread enabled, user should NOT call this function. + * + * @param timeout_ms, timeout value in ms. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_yield(int timeout_ms); + +typedef enum { + service_cota_callback_type_new_version_detected = 10, + + service_cota_callback_type_number, +} service_cota_callback_type_t; + +typedef void (*handle_service_cota_callback_fp_t)(service_cota_callback_type_t callback_type, const char *configid, + uint32_t configsize, + const char *gettype, + const char *sign, + const char *signmethod, + const char *cota_url); + +/** + * @brief this function used to register callback for config ota. + * + * @param callback_fp, user callback which register to cota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp); + +/** + * @brief this function used to execute cota process. + * + * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin. + * @param data_buf_length, data buf length that used to do ota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_cota_service(void *data_buf, int data_buf_length); + +/** + * @brief this function used to trigger cota process. + * + * @param config_scope, remote config scope, should be "product". + * @param get_type, remote config file type, should be "file". + * @param attribute_Keys, reserved. + * @param option, reserved. + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_cota_get_config(const char *config_scope, const char *get_type, + const char *attribute_Keys, void *option); + +typedef enum { + service_fota_callback_type_new_version_detected = 10, + + service_fota_callback_type_number, +} service_fota_callback_type_t; + +typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version); + +/** + * @brief this function used to register callback for firmware ota. + * + * @param callback_fp, user callback which register to fota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp); + +/** + * @brief this function used to execute fota process. + * + * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin. + * @param data_buf_length, data buf length that used to do ota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int being_deprecated linkkit_invoke_fota_service(void *data_buf, int data_buf_length); + +/** + * @brief this function used to get NTP time from cloud. + * + * @param ntp_reply_cb, user callback which register to ntp request. + * when cloud returns ntp reply, sdk would trigger the callback function + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_ntp_time_request(void (*ntp_reply_cb)(const char *ntp_offset_time_ms)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LINKKIT_EXPORT_H */ diff --git a/code/application/source/sf_app/component/liveMng/inc/exports/linkkit_gateway_export.h b/code/application/source/sf_app/component/liveMng/inc/exports/linkkit_gateway_export.h new file mode 100755 index 000000000..21724ad6d --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/exports/linkkit_gateway_export.h @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef LINKKIT_GATEWAY_EXPORT_H +#define LINKKIT_GATEWAY_EXPORT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef _WIN32 +#ifdef DLL_IOT_EXPORTS +#define DLL_IOT_API __declspec(dllexport) +#else +#define DLL_IOT_API __declspec(dllimport) +#endif +#else +#define DLL_IOT_API +#endif + +#if defined (__CC_ARM) +#define ssize_t int +#elif defined (__ICCARM__) +#define ssize_t int +#endif + +/***************************Gateway Interface***************************/ + +enum { + LINKKIT_EVENT_CLOUD_DISCONNECTED = 0, /* cloud disconnected */ + LINKKIT_EVENT_CLOUD_CONNECTED = 1, /* cloud connected */ + LINKKIT_EVENT_SUBDEV_DELETED = 2, /* subdev deleted */ + LINKKIT_EVENT_SUBDEV_PERMITED = 3, /* subdev permit join */ + LINKKIT_EVENT_SUBDEV_SETUP = 4, /* subdev install */ +}; + +/* + * option | default | minimum | maximum + *--------------------------------|---------|---------|--------- + * LINKKIT_OPT_MAX_MSG_SIZE | 20480 | 512 | 51200 + * LINKKIT_OPT_MAX_MSG_QUEUE_SIZE | 16 | 2 | 32 + * LINKKIT_OPT_THREAD_POOL_SIZE | 4 | 1 | 16 + * LINKKIT_OPT_THREAD_STACK_SIZE | 8192 | 1024 | 8388608 + * LINKKIT_OPT_LOG_LEVEL | 3 | 0 | 5 + */ + +enum { + LINKKIT_OPT_MAX_MSG_SIZE = 1, + LINKKIT_OPT_MAX_MSG_QUEUE_SIZE = 2, + LINKKIT_OPT_THREAD_POOL_SIZE = 3, + LINKKIT_OPT_THREAD_STACK_SIZE = 4, + LINKKIT_OPT_PROPERTY_POST_REPLY = 5, /* data type: int */ + LINKKIT_OPT_EVENT_POST_REPLY = 6, /* data type: int */ + LINKKIT_OPT_PROPERTY_SET_REPLY = 7 /* data type: int */ +}; + +typedef struct { + int event_type; /* see LINKKIT_EVENT_XXX for more details */ + + union { + struct { + char *productKey; + char *deviceName; + } subdev_deleted; + + struct { + char *productKey; + int timeoutSec; + } subdev_permited; + + struct { + char *subdevList; /* json format:[{"productKey":"","deviceName":""},...] */ + } subdev_install; + } event_data; +} linkkit_event_t; + +typedef struct linkkit_params_s { + int maxMsgSize; /* max message size */ + int maxMsgQueueSize; /* max message queue size */ + + int threadPoolSize; /* number threads in pool */ + int threadStackSize; /* default thread stack size */ + + int (*event_cb)(linkkit_event_t *ev, void *ctx); + + /* user private data */ + void *ctx; +} linkkit_params_t; + +/** + * @brief get default initialize parameters + * + * @return linkkit default parameters. + */ +linkkit_params_t *linkkit_gateway_get_default_params(void); + +/** + * @brief set option in paremeters + * + * @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params(). + * @param option, see LINKKIT_OPT_XXX for more detail. + * @param value, value of option. + * @param value_len, value length. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_setopt(linkkit_params_t *params, int option, void *value, int value_len); + +/** + * @brief set event callback + * + * @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params(). + * @param event_cb, event callback. + * @param ctx, user private data. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_set_event_callback(linkkit_params_t *params, int (*event_cb)(linkkit_event_t *ev, + void *ctx), + void *ctx); + +/** + * @brief linkkit initialization. + * + * @param initParams, linkkit initialize parameters, see linkkit_params_t for more detail. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_init(linkkit_params_t *initParams); + +/** + * @brief linkkit deinitialization. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_exit(void); + +typedef struct { + + int (*register_complete)(void *ctx); + /** + * @brief get property callback. + * + * @param in, properties to be get, in JSON array format, terminated by NULL. + * @param out, output buffer fill by user, in json format, terminated by NULL. + * @param out_len, out buffer length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create() + * + * @return 0 when success, -1 when fail. + */ + int (*get_property)(char *in, char *out, int out_len, void *ctx); + + /** + * @brief set property callback. + * + * @param in, properties to be set, in JSON object format, terminated by NULL. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create() + * + * @return 0 when success, -1 when fail. + */ + int (*set_property)(char *in, void *ctx); + + /** + * @brief call service callback. + * + * @param identifier, service identifier, available services define in TSL file. + * @param in, service input data, in JSON object format, terminated by NULL. + * @param out, service output, this buffer will be filled by user, in json format, terminated by NULL. + * @param out_len, out buffer length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ + int (*call_service)(char *identifier, char *in, char *out, int out_len, void *ctx); + + /** + * @brief raw data from cloud. + * + * @param in, input data from cloud. + * @param in_len, input data length. + * @param out, output data to cloud, allocated by linkkit fill by user, no need to be free. + * @param out_len, out buffer length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * + * @return output data size. < 0 when fail. + */ + ssize_t (*down_rawdata)(const void *in, int in_len, void *out, int out_len, void *ctx); + + /** + * @brief return data from cloud when calling linkkit_gateway_post_rawdata(). + * + * @param data, return raw data from cloud. + * @param len, data length. + * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ + int (*post_rawdata_reply)(const void *data, int len, void *ctx); +} linkkit_cbs_t; + +/** + * @brief start linkkit gateway routines and install callback funstions. + * + * @param cbs, callback function struct to be installed. + * @param ctx, user context pointer. + * + * @return device id, 0 > when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_start(linkkit_cbs_t *cbs, void *ctx); + +/** + * @brief stop linkkit gateway. + + * @param devid, device id return from linkkit_gateway_start(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_stop(int devid); + +/** + * @brief register subdev to gateway. + + * @param productKey, subdev's product key. + * @param deviceName, subdev's device name. + * @param deviceSecret, subdev's device secret. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_register(char *productKey, char *deviceName, char *deviceSecret); + +/** + * @brief deregister subdev from gateway. + + * @param productKey, subdev's product key. + * @param deviceName, subdev's device name. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_unregister(char *productKey, char *deviceName); + +/** + * @brief create subdev and install callback funstions. + * + * @param productKey, subdev's product key. + * @param deviceName, subdev's device name. + * @param cbs, callback function struct to be installed. + * @param ctx, user context pointer. + * + * @return device id, 0 > when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_create(char *productKey, char *deviceName, linkkit_cbs_t *cbs, void *ctx); + +/** + * @brief destroy subdev by device id. + + * @param devid, device id return from linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_destroy(int devid); + +/** + * @brief make subdev accessible from cloud. + + * @param devid, device id return from linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_login(int devid); + +/** + * @brief make subdev inaccessible on cloud. + + * @param devid, device id return from linkkit_gateway_subdev_create(). + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_subdev_logout(int devid); + +enum { + LINKKIT_STATE_ENABLED = 0, /* device is enabled by cloud */ + LINKKIT_STATE_DISABLED, /* device is disabled by cloud */ + LINKKIT_STATE_REMOVED, /* device is deleted by cloud */ +}; + +typedef struct { + char *productKey; /* device's product key */ + char *deviceName; /* device's device name */ + + int devtype; /* Device Type: 0 - gateway, 1 - subdev */ + int login; /* Login State: 0 - logout, 1 - login */ + int state; /* Device State: see LINKKIT_STATE_xxx */ + int online; /* 0 - offline, 1 - online */ +} linkkit_devinfo_t; + +/** + * @brief get device infomation specific by devid. + * + * @param devinfo, device information, see linkkit_devinfo_t for more detail. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_get_devinfo(int devid, linkkit_devinfo_t *devinfo); + +/** + * @brief post event to cloud. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param identifier, event identifier, see tsl file for more detail. + * @param event, event data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_trigger_event_json_sync(int devid, char *identifier, char *event, int timeout_ms); + +/** + * @brief post event to cloud asynchronously. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param identifier, event identifier, see tsl file for more detail. + * @param event, event data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0). + * @param ctx, user data passed to 'func'. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_trigger_event_json(int devid, char *identifier, char *event, int timeout_ms, + void (*func)(int retval, void *ctx), void *ctx); + + +/** + * @brief post property to cloud. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param property, property data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_property_json_sync(int devid, char *property, int timeout_ms); + +/** + * @brief post property to cloud asynchronously. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param property, property data, in JSON format. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0). + * @param ctx, user data passed to 'func'. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_property_json(int devid, char *property, int timeout_ms, + void (*func)(int retval, void *ctx), + void *ctx); + +/** + * @brief post raw data to cloud. + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param data, raw data buffer pointer. + * @param len, raw data length. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_rawdata(int devid, void *data, int len); + +typedef enum { + LINKKIT_OTA_EVENT_NEW_VERSION_DETECTED = 1, +} linkkit_ota_event_t; + +typedef enum { + service_fota_callback_type_new_version_detected = 10, + + service_fota_callback_type_number, +} service_fota_callback_type_t; + +typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version); + +/** + * @brief this function used to register callback for firmware ota. + * + * @param callback_fp, user callback which register to fota. (NULL for unregister) + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_fota_init(handle_service_fota_callback_fp_t callback_fp); + +/** + * @brief this function used to execute fota process. + * + * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin. + * @param data_buf_length, data buf length that used to do ota. + * + * @return 0 when success, -1 when fail. + */ +DLL_IOT_API int linkkit_gateway_invoke_fota_service(void *data_buf, int data_buf_length); + +typedef struct { + char *attrKey; /* the key of extend info. */ + char *attrValue; /* the value of extend info. */ +} linkkit_extinfo_t; + +/** + * @brief post group of extend info to cloud + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param extinfos, group of extend info to be post. + * @param nb_extinfos, number of extend infos in extinfos. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_post_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos, + int timeout_ms); + +/** + * @brief delete extend info specific by key + * + * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create(). + * @param extinfos, group of extend info to be deleted, attrValue in linkkit_extinfo_t will be ignore. + * @param nb_extinfos, number of extend infos in extinfos. + * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response. + * + * @return 0 when success, < 0 when fail. + */ +DLL_IOT_API int linkkit_gateway_delete_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos, + int timeout_ms); + +/** + * @brief get number devices currently in gateway + * + * @return number devinfos. + */ +DLL_IOT_API int linkkit_gateway_get_num_devices(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LINKKIT_GATEWAY_EXPORT_H */ diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_awss.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_awss.h new file mode 100755 index 000000000..64ff0062e --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_awss.h @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_IMPORT_AWSS_H__ +#define __IOT_IMPORT_AWSS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _IN_OPT_ +#define _IN_OPT_ +#endif + +#ifndef DLL_HAL_API +#define DLL_HAL_API +#endif + +#ifndef _IN_ +#define _IN_ +#endif + +#ifndef _OU_ +#define _OU_ +#endif + + +#define STR_SHORT_LEN (32) +#ifndef ETH_ALEN +#define ETH_ALEN (6) +#endif +#define HAL_MAX_SSID_LEN (32 + 1) /* ssid: 32 octets at most, include the NULL-terminated */ +#define HAL_MAX_PASSWD_LEN (64 + 1) /* password: 8-63 ascii */ +#define WLAN_CONNECTION_TIMEOUT_MS (30 * 1000) + +/** + * @brief 获取配网服务(`AWSS`)的超时时间长度, 单位是毫秒 + * + * @return 超时时长, 单位是毫秒 + * @note 推荐时长是60,0000毫秒 + */ +DLL_HAL_API int HAL_Awss_Get_Timeout_Interval_Ms(void); + +/** + * @brief 获取在每个信道(`channel`)上扫描的时间长度, 单位是毫秒 + * + * @return 时间长度, 单位是毫秒 + * @note 推荐时长是200毫秒到400毫秒 + */ +DLL_HAL_API int HAL_Awss_Get_Channelscan_Interval_Ms(void); + +/* link type */ +enum AWSS_LINK_TYPE { + /* rtos HAL choose this type */ + AWSS_LINK_TYPE_NONE, + + /* linux HAL may choose the following type */ + AWSS_LINK_TYPE_PRISM, + AWSS_LINK_TYPE_80211_RADIO, + AWSS_LINK_TYPE_80211_RADIO_AVS, + AWSS_LINK_TYPE_HT40_CTRL /* for espressif HAL, see struct ht40_ctrl */ +}; + +struct HAL_Ht40_Ctrl { + uint16_t length; + uint8_t filter; + signed char rssi; +}; + +/** + * @brief 802.11帧的处理函数, 可以将802.11 Frame传递给这个函数 + * + * @param[in] buf @n 80211 frame buffer, or pointer to struct ht40_ctrl + * @param[in] length @n 80211 frame buffer length + * @param[in] link_type @n AWSS_LINK_TYPE_NONE for most rtos HAL, + * and for linux HAL, do the following step to check + * which header type the driver supported. + @verbatim + a) iwconfig wlan0 mode monitor #open monitor mode + b) iwconfig wlan0 channel 6 #switch channel 6 + c) tcpdump -i wlan0 -s0 -w file.pacp #capture 80211 frame & save + d) open file.pacp with wireshark or omnipeek + check the link header type and fcs included or not + @endverbatim + * @param[in] with_fcs @n 80211 frame buffer include fcs(4 byte) or not + * @param[in] rssi @n rssi of packet, range of [-127, -1] + */ +typedef int (*awss_recv_80211_frame_cb_t)(char *buf, int length, + enum AWSS_LINK_TYPE link_type, int with_fcs, signed char rssi); + +/** + * @brief 设置Wi-Fi网卡工作在监听(Monitor)模式, 并在收到802.11帧的时候调用被传入的回调函数 + * + * @param[in] cb @n A function pointer, called back when wifi receive a frame. + */ +DLL_HAL_API void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb); + +/** + * @brief 设置Wi-Fi网卡离开监听(Monitor)模式, 并开始以站点(Station)模式工作 + */ +DLL_HAL_API void HAL_Awss_Close_Monitor(void); + +/** + * @brief 开启设备热点(SoftAP模式) + * + * @param[in] ssid @n 热点的ssid字符; + * @param[in] passwd @n 热点的passwd字符; + * @param[in] beacon_interval @n 热点的Beacon广播周期(广播间隔); + * @param[in] hide @n 是否是隐藏热点,hide:0, 非隐藏, 其它值:隐藏; + * @return, + @verbatim + = 0: success + = -1: unsupported + = -2: failure with system error + = -3: failure with no memory + = -4: failure with invalid parameters + @endverbatim + * @Note: + * 1)ssid和passwd都是以'\0'结尾的字符串,如果passwd字符串的 + * 长度为0,表示该热点采用Open模式(不加密); + * 2)beacon_interval表示热点的Beacon广播间隔(或周期),单 + * 位为毫秒,一般会采用默认100ms; + * 3)hide表示创建的热点是否是隐藏热点,hide=0表示非隐藏热 + * 点,其他值表示隐藏热点; + */ + +DLL_HAL_API int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide); + +/** + * @brief 关闭当前设备热点,并把设备由SoftAP模式切换到Station模式 + * + * @return, + @verbatim + = 0: success + = -1: unsupported + = -2: failure + @endverbatim + * @Note: + * 1)如果当前设备已经开启热点,关闭当前热点,如果当前设备正 + * 在开热点,取消开热点的操作; + * 2)如果当前设备不是以Station模式(包括Station+SoftAP模式和 + * SoftAP模式)工作,设备必须切换到Station模式; + * 3)Wi-Fi状态机需要切换到初始化状态,因为接下来很可能进行 + * 连接某一个路由器操作; + */ + +DLL_HAL_API int HAL_Awss_Close_Ap(); + +/** + * @brief 设置Wi-Fi网卡切换到指定的信道(channel)上 + * + * @param[in] primary_channel @n Primary channel. + * @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is supported, currently + * this param is always 0. + * @param[in] bssid @n A pointer to wifi BSSID on which awss lock the channel, most HAL + * may ignore it. + */ +DLL_HAL_API void HAL_Awss_Switch_Channel( + _IN_ char primary_channel, + _IN_OPT_ char secondary_channel, + _IN_OPT_ uint8_t bssid[ETH_ALEN]); + +/* auth type */ +enum AWSS_AUTH_TYPE { + AWSS_AUTH_TYPE_OPEN, + AWSS_AUTH_TYPE_SHARED, + AWSS_AUTH_TYPE_WPAPSK, + AWSS_AUTH_TYPE_WPA8021X, + AWSS_AUTH_TYPE_WPA2PSK, + AWSS_AUTH_TYPE_WPA28021X, + AWSS_AUTH_TYPE_WPAPSKWPA2PSK, + AWSS_AUTH_TYPE_MAX = AWSS_AUTH_TYPE_WPAPSKWPA2PSK, + AWSS_AUTH_TYPE_INVALID = 0xff, +}; + +/* encryt type */ +enum AWSS_ENC_TYPE { + AWSS_ENC_TYPE_NONE, + AWSS_ENC_TYPE_WEP, + AWSS_ENC_TYPE_TKIP, + AWSS_ENC_TYPE_AES, + AWSS_ENC_TYPE_TKIPAES, + AWSS_ENC_TYPE_MAX = AWSS_ENC_TYPE_TKIPAES, + AWSS_ENC_TYPE_INVALID = 0xff, +}; + +/** + * @brief 要求Wi-Fi网卡连接指定热点(Access Point)的函数 + * + * @param[in] connection_timeout_ms @n AP connection timeout in ms or HAL_WAIT_INFINITE + * @param[in] ssid @n AP ssid + * @param[in] passwd @n AP passwd + * @param[in] auth @n optional(AWSS_AUTH_TYPE_INVALID), AP auth info + * @param[in] encry @n optional(AWSS_ENC_TYPE_INVALID), AP encry info + * @param[in] bssid @n optional(NULL or zero mac address), AP bssid info + * @param[in] channel @n optional, AP channel info + * @return + @verbatim + = 0: connect AP & DHCP success + = -1: connect AP or DHCP fail/timeout + @endverbatim + * @see None. + * @note + * If the STA connects the old AP, HAL should disconnect from the old AP firstly. + * If bssid specifies the dest AP, HAL should use bssid to connect dest AP. + */ +DLL_HAL_API int HAL_Awss_Connect_Ap( + _IN_ uint32_t connection_timeout_ms, + _IN_ char ssid[HAL_MAX_SSID_LEN], + _IN_ char passwd[HAL_MAX_PASSWD_LEN], + _IN_OPT_ enum AWSS_AUTH_TYPE auth, + _IN_OPT_ enum AWSS_ENC_TYPE encry, + _IN_OPT_ uint8_t bssid[ETH_ALEN], + _IN_OPT_ uint8_t channel); + +/* 80211 frame type */ +typedef enum HAL_Awss_Frame_Type { + FRAME_ACTION, + FRAME_BEACON, + FRAME_PROBE_REQ, + FRAME_PROBE_RESPONSE, + FRAME_DATA +} HAL_Awss_Frame_Type_t; + +#define FRAME_ACTION_MASK (1 << FRAME_ACTION) +#define FRAME_BEACON_MASK (1 << FRAME_BEACON) +#define FRAME_PROBE_REQ_MASK (1 << FRAME_PROBE_REQ) +#define FRAME_PROBE_RESP_MASK (1 << FRAME_PROBE_RESPONSE) +#define FRAME_DATA_MASK (1 << FRAME_DATA) + +/** + * @brief 在当前信道(channel)上以基本数据速率(1Mbps)发送裸的802.11帧(raw 802.11 frame) + * + * @param[in] type @n see enum HAL_Awss_frame_type, currently only FRAME_BEACON + * FRAME_PROBE_REQ is used + * @param[in] buffer @n 80211 raw frame, include complete mac header & FCS field + * @param[in] len @n 80211 raw frame length + * @return + @verbatim + = 0, send success. + = -1, send failure. + = -2, unsupported. + @endverbatim + * @see None. + * @note awss use this API send raw frame in wifi monitor mode & station mode + */ +DLL_HAL_API int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type, + _IN_ uint8_t *buffer, _IN_ int len); + +/** + * @brief 管理帧的处理回调函数 + * + * @param[in] buffer @n 80211 raw frame or ie(information element) buffer + * @param[in] len @n buffer length + * @param[in] rssi_dbm @n rssi in dbm, range of [-127, -1], set it to -1 if not supported + * @param[in] buffer_type @n 0 when buffer is a 80211 frame, + * 1 when buffer only contain IE info + * @return None. + * @see None. + * @note None. + */ +typedef void (*awss_wifi_mgmt_frame_cb_t)(_IN_ uint8_t *buffer, _IN_ int len, + _IN_ signed char rssi_dbm, _IN_ int buffer_type); + +/** + * @brief 使能或禁用对管理帧的过滤 + * + * @param[in] filter_mask @n see mask macro in enum HAL_Awss_frame_type, + * currently only FRAME_PROBE_REQ_MASK & FRAME_BEACON_MASK is used + * @param[in] vendor_oui @n oui can be used for precise frame match, optional + * @param[in] callback @n see awss_wifi_mgmt_frame_cb_t, passing 80211 + * frame or ie to callback. when callback is NULL + * disable sniffer feature, otherwise enable it. + * @return + @verbatim + = 0, success + = -1, fail + = -2, unsupported. + @endverbatim + * @see None. + * @note awss use this API to filter specific mgnt frame in wifi station mode + */ +DLL_HAL_API int HAL_Wifi_Enable_Mgmt_Frame_Filter( + _IN_ uint32_t filter_mask, + _IN_OPT_ uint8_t vendor_oui[3], + _IN_ awss_wifi_mgmt_frame_cb_t callback); + +typedef struct { + enum AWSS_AUTH_TYPE auth; + enum AWSS_ENC_TYPE encry; + uint8_t channel; + signed char rssi_dbm; + char ssid[HAL_MAX_SSID_LEN]; + uint8_t mac[ETH_ALEN]; +} awss_ap_info_t; + +/** + * @brief handle one piece of AP information from wifi scan result + * + * @param[in] ssid @n name of AP + * @param[in] bssid @n mac address of AP + * @param[in] channel @n AP channel + * @param[in] rssi @n rssi range[-127, -1]. + * the higher the RSSI number, the stronger the signal. + * @param[in] is_last_ap @n this AP information is the last one if is_last_ap > 0. + * this AP information is not the last one if is_last_ap == 0. + * @return 0 for wifi scan is done, otherwise return -1 + * @see None. + * @note None. + */ +typedef int (*awss_wifi_scan_result_cb_t)( + const char ssid[HAL_MAX_SSID_LEN], + const uint8_t bssid[ETH_ALEN], + enum AWSS_AUTH_TYPE auth, + enum AWSS_ENC_TYPE encry, + uint8_t channel, signed char rssi, + int is_last_ap); + +/** + * @brief 启动一次Wi-Fi的空中扫描(Scan) + * + * @param[in] cb @n pass ssid info(scan result) to this callback one by one + * @return 0 for wifi scan is done, otherwise return -1 + * @see None. + * @note + * This API should NOT exit before the invoking for cb is finished. + * This rule is something like the following : + * HAL_Wifi_Scan() is invoked... + * ... + * for (ap = first_ap; ap <= last_ap; ap = next_ap){ + * cb(ap) + * } + * ... + * HAL_Wifi_Scan() exit... + */ +DLL_HAL_API int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb); + +/** + * @brief 获取所连接的热点(Access Point)的信息 + * + * @param[out] ssid: array to store ap ssid. It will be null if ssid is not required. + * @param[out] passwd: array to store ap password. It will be null if ap password is not required. + * @param[out] bssid: array to store ap bssid. It will be null if bssid is not required. + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note + * If the STA dosen't connect AP successfully, HAL should return -1 and not touch the ssid/passwd/bssid buffer. + */ +DLL_HAL_API int HAL_Wifi_Get_Ap_Info( + _OU_ char ssid[HAL_MAX_SSID_LEN], + _OU_ char passwd[HAL_MAX_PASSWD_LEN], + _OU_ uint8_t bssid[ETH_ALEN]); + +/** + * @brief 获取`smartconfig`服务的安全等级 + * + * @param None. + * @return The security level: + @verbatim + 0: open (no encrypt) + 1: aes256cfb with default aes-key and aes-iv + 2: aes128cfb with default aes-key and aes-iv + 3: aes128cfb with aes-key per product and aes-iv = 0 + 4: aes128cfb with aes-key per device and aes-iv = 0 + 5: aes128cfb with aes-key per manufacture and aes-iv = 0 + others: invalid + @endverbatim + * @see None. + */ +DLL_HAL_API int HAL_Awss_Get_Encrypt_Type(void); + +/** + * @brief Get Security level for wifi configuration with connection. + * Used for AP solution of router and App. + * + * @param None. + * @return The security level: + @verbatim + 3: aes128cfb with aes-key per product and aes-iv = random + 4: aes128cfb with aes-key per device and aes-iv = random + 5: aes128cfb with aes-key per manufacture and aes-iv = random + others: invalid + @endverbatim + * @see None. + */ +DLL_HAL_API int HAL_Awss_Get_Conn_Encrypt_Type(void); + +/** + * @brief 获取当前Station模式与AP连接状态的信息 + * + * @param[out] p_rssi: rssi value of current link + * @param[out] p_channel: channel of current link + * + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + * @note awss use this API to get rssi and channel of current link + */ +DLL_HAL_API int HAL_Wifi_Get_Link_Stat(_OU_ int *p_rssi, + _OU_ int *p_channel); + +#ifdef __cplusplus +} +#endif + +#endif /* __IOT_IMPORT_AWSS_H__ */ + diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_config.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_config.h new file mode 100755 index 000000000..5a2bbd41c --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_config.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef __IOT_IMPORT_CONFIG_H__ +#define __IOT_IMPORT_CONFIG_H__ + +#ifndef CONFIG_HTTP_AUTH_TIMEOUT + #define CONFIG_HTTP_AUTH_TIMEOUT (5 * 1000) +#endif + +#ifndef CONFIG_MID_HTTP_TIMEOUT + #define CONFIG_MID_HTTP_TIMEOUT (5 * 1000) +#endif + +#ifndef CONFIG_GUIDER_AUTH_TIMEOUT + #define CONFIG_GUIDER_AUTH_TIMEOUT (10 * 1000) +#endif + +#ifndef CONFIG_COAP_AUTH_TIMEOUT + #define CONFIG_COAP_AUTH_TIMEOUT (3 * 1000) +#endif + +#ifndef CONFIG_MQTT_TX_MAXLEN + #ifndef LINK_VISUAL_ENABLE + #define CONFIG_MQTT_TX_MAXLEN (2048) + #else + #define CONFIG_MQTT_TX_MAXLEN (16*1024) + #endif +#endif + +#ifndef CONFIG_MQTT_RX_MAXLEN + #ifndef LINK_VISUAL_ENABLE + #define CONFIG_MQTT_RX_MAXLEN (2048) + #else + #define CONFIG_MQTT_RX_MAXLEN (16*1024) + #endif +#endif + +#ifndef CONFIG_SDK_THREAD_COST + #define CONFIG_SDK_THREAD_COST (0) +#endif + +#ifndef CONFIG_MBEDTLS_DEBUG_LEVEL + #define CONFIG_MBEDTLS_DEBUG_LEVEL (0) +#endif + +#ifndef CONFIG_RUNTIME_LOG_LEVEL + #define CONFIG_RUNTIME_LOG_LEVEL (2) +#endif + +#ifndef CONFIG_BLDTIME_MUTE_DBGLOG + #define CONFIG_BLDTIME_MUTE_DBGLOG (0) +#endif + +#ifndef CONFIG_DISPATCH_QUEUE_MAXLEN + #ifndef LINK_VISUAL_ENABLE + #define CONFIG_DISPATCH_QUEUE_MAXLEN (20) + #else + #define CONFIG_DISPATCH_QUEUE_MAXLEN (160) + #endif +#endif + +#ifndef CONFIG_DISPATCH_PACKET_MAXCOUNT + #define CONFIG_DISPATCH_PACKET_MAXCOUNT (0) +#endif + +#ifndef CONFIG_MSGCACHE_QUEUE_MAXLEN + #define CONFIG_MSGCACHE_QUEUE_MAXLEN (20) +#endif + +#endif /* __IOT_IMPORT_CONFIG_H__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_crypt.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_crypt.h new file mode 100755 index 000000000..aa05b667e --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_crypt.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef __IOT_IMPORT_CRYPT_H__ +#define __IOT_IMPORT_CRYPT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + HAL_AES_ENCRYPTION = 0, + HAL_AES_DECRYPTION = 1, +} AES_DIR_t; + +typedef void *p_HAL_Aes128_t; + +/** + * @brief 初始化AES加密的结构体 + * + * @param[in] key: + * @param[in] iv: + * @param[in] dir: AES_ENCRYPTION or AES_DECRYPTION + * @return AES128_t + @verbatim None + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); + +/** + * @brief 销毁AES加密的结构体 + * + * @param[in] aes: + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); + +/** + * @brief 以`AES-CBC-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥加密指定的明文 + * + * @param[in] aes: AES handler + * @param[in] src: plain data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: cipher data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Cbc_Encrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t blockNum, + _OU_ void *dst); + +/** + * @brief 以`AES-CBC-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥解密指定的密文 + * + * @param[in] aes: AES handler + * @param[in] src: cipher data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: plain data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Cbc_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t blockNum, + _OU_ void *dst); + +/** + * @brief 以`AES-CFB-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥加密指定的明文 + * + * @param[in] aes: AES handler + * @param[in] src: plain data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: cipher data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ + +DLL_HAL_API int HAL_Aes128_Cfb_Encrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t length, + _OU_ void *dst); + +/** + * @brief 以`AES-CFB-128`方式, 根据`HAL_Aes128_Init()`时传入的密钥解密指定的密文 + * + * @param[in] aes: AES handler + * @param[in] src: cipher data + * @param[in] blockNum: plain data number of 16 bytes size + * @param[out] dst: plain data + * @return + @verbatim + = 0: succeeded + = -1: failed + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Aes128_Cfb_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t length, + _OU_ void *dst); + +#ifdef __cplusplus +} +#endif + +#endif /* __IOT_IMPORT_CRYPT_H__ */ + diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_dtls.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_dtls.h new file mode 100755 index 000000000..50a8acf6b --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_dtls.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_DTLS_H__ +#define __IMPORT_DTLS_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include +#include + +#define DTLS_ERROR_BASE (1<<24) +#define DTLS_SUCCESS (0) +#define DTLS_INVALID_PARAM (DTLS_ERROR_BASE | 1) +#define DTLS_INVALID_CA_CERTIFICATE (DTLS_ERROR_BASE | 2) +#define DTLS_HANDSHAKE_IN_PROGRESS (DTLS_ERROR_BASE | 3) +#define DTLS_HANDSHAKE_FAILED (DTLS_ERROR_BASE | 4) +#define DTLS_FATAL_ALERT_MESSAGE (DTLS_ERROR_BASE | 5) +#define DTLS_PEER_CLOSE_NOTIFY (DTLS_ERROR_BASE | 6) +#define DTLS_SESSION_CREATE_FAILED (DTLS_ERROR_BASE | 7) +#define DTLS_READ_DATA_FAILED (DTLS_ERROR_BASE | 8) + +typedef struct { + void *(*malloc)(uint32_t size); + void (*free)(void *ptr); +} dtls_hooks_t; + +typedef struct { + unsigned char *p_ca_cert_pem; + char *p_host; + unsigned short port; +} coap_dtls_options_t; + +typedef void DTLSContext; + +/** @defgroup group_platform platform + * @{ + */ + + +/** @defgroup group_platform_dtls dtls + * @{ + */ + +/** + * @brief Set malloc/free function. + * + * @param [in] hooks: @n Specify malloc/free function you want to use + * + * @retval DTLS_SUCCESS : Success. + @retval other : Fail. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_DTLSHooks_set(dtls_hooks_t *hooks); + +/** + * @brief Establish a DSSL connection. + * + * @param [in] p_options: @n Specify paramter of DTLS + @verbatim + p_host : @n Specify the hostname(IP) of the DSSL server + port : @n Specify the DSSL port of DSSL server + p_ca_cert_pem : @n Specify the root certificate which is PEM format. + @endverbatim + * @return DSSL handle. + * @see None. + * @note None. + */ +DLL_HAL_API DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options); + +/** + * @brief Write data into the specific DSSL connection. + * + * @param [in] context @n A descriptor identifying a connection. + * @param [in] p_data @n A pointer to a buffer containing the data to be transmitted. + * @param [in] p_datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @retval DTLS_SUCCESS : Success. + @retval other : Fail. + * @see None. + */ +DLL_HAL_API unsigned int HAL_DTLSSession_write(DTLSContext *context, + const unsigned char *p_data, + unsigned int *p_datalen); +/** + * @brief Read data from the specific DSSL connection with timeout parameter. + * The API will return immediately if len be received from the specific DSSL connection. + * + * @param [in] context @n A descriptor identifying a DSSL connection. + * @param [in] p_data @n A pointer to a buffer to receive incoming data. + * @param [in] p_datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * @return The result of read data from DSSL connection + * @retval DTLS_SUCCESS : Read success. + * @retval DTLS_FATAL_ALERT_MESSAGE : Recv peer fatal alert message. + * @retval DTLS_PEER_CLOSE_NOTIFY : The DTLS session was closed by peer. + * @retval DTLS_READ_DATA_FAILED : Read data fail. + * @see None. + */ +DLL_HAL_API unsigned int HAL_DTLSSession_read(DTLSContext *context, + unsigned char *p_data, + unsigned int *p_datalen, + unsigned int timeout_ms); +/** + * @brief Destroy the specific DSSL connection. + * + * @param[in] context: @n Handle of the specific connection. + * + * @return The result of free dtls session + * @retval DTLS_SUCCESS : Read success. + * @retval DTLS_INVALID_PARAM : Invalid parameter. + * @retval DTLS_INVALID_CA_CERTIFICATE : Invalid CA Certificate. + * @retval DTLS_HANDSHAKE_IN_PROGRESS : Handshake in progress. + * @retval DTLS_HANDSHAKE_FAILED : Handshake failed. + * @retval DTLS_FATAL_ALERT_MESSAGE : Recv peer fatal alert message. + * @retval DTLS_PEER_CLOSE_NOTIFY : The DTLS session was closed by peer. + * @retval DTLS_SESSION_CREATE_FAILED : Create session fail. + * @retval DTLS_READ_DATA_FAILED : Read data fail. + */ +DLL_HAL_API unsigned int HAL_DTLSSession_free(DTLSContext *context); + +/** @} */ /* end of platform_dtls */ +/** @} */ /* end of platform */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_kv.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_kv.h new file mode 100755 index 000000000..7a88decbf --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_kv.h @@ -0,0 +1,33 @@ +/** + * @file iot_import_kv.h + * @brief + * @date 2021-04-29 + * + * @copyright Copyright (C) 2017-2020 Alibaba Group Holding Limited + * + * @details + * + */ + +#ifndef __IOT_IMPORTS_KV_H__ +#define __IOT_IMPORTS_KV_H__ + +#if defined(__cplusplus) +extern "C" +{ +#endif + + extern int aos_kv_init(void); + extern int aiot_kv_init(void); + extern void aos_kv_deinit(void); + + extern int aos_kv_set(const char *key, const void *val, int len, int sync); + extern int aos_kv_get(const char *key, void *buffer, int *buffer_len); + extern int aos_kv_del(const char *key); + extern int aos_kv_del_by_prefix(const char *prefix); + +#if defined(__cplusplus) +} +#endif + +#endif /* #ifndef __AIOT_KV_API_H__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_ota.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_ota.h new file mode 100755 index 000000000..270ceb360 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_ota.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_IMPORT_OTA_H__ +#define __IOT_IMPORT_OTA_H__ + +/***************************** firmware upgrade interface *****************************/ + +/** @defgroup group_platform_ota ota + * @{ + */ + +/** + * @brief initialize a firmware upgrade. + * + * @param None + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Firmware_Persistence_Start(void); + + +/** + * @brief save firmware upgrade data to flash. + * + * @param[in] buffer: @n A pointer to a buffer to save data. + * @param[in] length: @n The length, in bytes, of the data pointed to by the buffer parameter. + * @return 0, Save success; -1, Save failure. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Firmware_Persistence_Write(_IN_ char *buffer, _IN_ uint32_t length); + + +/** + * @brief indicate firmware upgrade data complete, and trigger data integrity checking, + and then reboot the system. + * + * @param None. + * @return 0: Success; -1: Failure. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Firmware_Persistence_Stop(void); + +#endif /* __IOT_IMPORT_UOTA_H__ */ + diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_product.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_product.h new file mode 100755 index 000000000..237407c2a --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_product.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_PRODUCT_H__ +#define __IMPORT_PRODUCT_H__ + +#define MAC_ADDR_LEN_MAX (10) +#define PID_STRLEN_MAX (64) +#define MID_STRLEN_MAX (64) +#define IOTX_URI_MAX_LEN (135) /* IoTx CoAP/HTTP uri & MQTT topic maximal length */ +#define PID_STR_MAXLEN (64) +#define MID_STR_MAXLEN (64) +#define PRODUCT_KEY_MAXLEN (20 + 1) +#define DEVICE_NAME_MAXLEN (32 + 1) +#define DEVICE_ID_MAXLEN (64 + 1) +#define DEVICE_SECRET_MAXLEN (64 + 1) +#define PRODUCT_SECRET_MAXLEN (64 + 1) +#define FIRMWARE_VERSION_MAXLEN (64 + 1) +#define HAL_CID_LEN (64 + 1) + +/** + * @brief 获取设备的固件版本字符串 + * + * @param version : 用来存放版本字符串的数组 + * @return 写到version[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetFirmwareVersion(_OU_ char version[FIRMWARE_VERSION_MAXLEN]); + +/** + * @brief 获取设备的`Partner ID`, 仅用于紧密合作伙伴 + * + * @param pid_str : 用来存放Partner ID字符串的数组 + * @return 写到pid_str[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetPartnerID(_OU_ char pid_str[PID_STR_MAXLEN]); + +/** + * @brief 获取设备的`Module ID`, 仅用于紧密合作伙伴 + * + * @param mid_str : 用来存放Module ID字符串的数组 + * @return 写到mid_str[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetModuleID(_OU_ char mid_str[MID_STR_MAXLEN]); + + +/** + * @brief 获取设备的`DeviceID`, 用于标识设备单品的ID + * + * @param device_id : 用来存放DeviceID字符串的数组 + * @return 写到device_id[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetDeviceID(_OU_ char device_id[DEVICE_ID_LEN]); + +/** + * @brief 获取唯一的芯片ID字符串 + * + * @param cid_str : 存放芯片ID字符串的缓冲区数组 + * @return 指向缓冲区数组的起始地址 + */ +char *HAL_GetChipID(_OU_ char cid_str[HAL_CID_LEN]); + +/** + * @brief 设置设备的`ProductKey`, 用于标识设备的品类, 三元组之一 + * + * @param product_key : 用来存放ProductKey字符串的数组 + * @return 写到product_key[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetProductKey(_IN_ char *product_key); + +/** + * @brief 设置设备的`DeviceName`, 用于标识设备单品的名字, 三元组之一 + * + * @param device_name : 用来存放DeviceName字符串的数组 + * @return 写到device_name[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetDeviceName(_IN_ char *device_name); + +/** + * @brief 设置设备的`DeviceSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param device_secret : 用来存放DeviceSecret字符串的数组 + * @return 写到device_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetDeviceSecret(_IN_ char *device_secret); + +/** + * @brief 设置设备的`ProductSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param product_secret : 用来存放ProductSecret字符串的数组 + * @return 写到product_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_SetProductSecret(_IN_ char *product_secret); + +/** + * @brief 获取设备的`ProductKey`, 用于标识设备的品类, 三元组之一 + * + * @param product_key : 用来存放ProductKey字符串的数组 + * @return 写到product_key[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetProductKey(_OU_ char product_key[PRODUCT_KEY_LEN]); + +/** + * @brief 获取设备的`DeviceName`, 用于标识设备单品的名字, 三元组之一 + * + * @param device_name : 用来存放DeviceName字符串的数组 + * @return 写到device_name[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetDeviceName(_OU_ char device_name[DEVICE_NAME_LEN]); + +/** + * @brief 获取设备的`DeviceSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param device_secret : 用来存放DeviceSecret字符串的数组 + * @return 写到device_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetDeviceSecret(_OU_ char device_secret[DEVICE_SECRET_LEN]); + +/** + * @brief 获取设备的`ProductSecret`, 用于标识设备单品的密钥, 三元组之一 + * + * @param product_secret : 用来存放ProductSecret字符串的数组 + * @return 写到product_secret[]数组中的字符长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_GetProductSecret(_OU_ char product_secret[DEVICE_SECRET_LEN]); + +#define NIF_STRLEN_MAX (160) + +/** + ** @brief Retrieves all the info of the current network interfaces, + ** including eth Mac, WiFi Mac, and IMEI/ICCID/IMSI/MSISDN for cellular connections. + ** Note that the network interface length MUST NOT exceed NIF_STRLEN_MAX + ** + ** @param [nif_str] give buffer to save network interface + ** @return the lenth of the nif_str info + ** @see None. + ** @note None. + **/ +DLL_HAL_API int HAL_GetNetifInfo(char *nif_str); + +/** + * 这个Hal主要用于解决三元组烧重的问题. 如果不涉及这个问题, 则请忽略这个Hal. + * + * @breif 获取设备的唯一标识符(uuid) + * 这里的uuid, 主要用于在多个设备都烧了相同三元组情况下能够区分不同设备,不要求全球唯一,但要求对同一个设备始终保持不变 + * 用户可以从IMEI/mac地址/cpu序列号等信息中择一作为设备的uuid + * + * 考虑到部分设备会用mac地址作为uuid, 而少量设备的mac地址会偶现无法读取成功的情况, 或者每次读出来都不一样的情况, + * 首选的方案为步骤3, 即将uuid+time的信息持久化到一片恢复出厂设置/固件升级也不会被erase掉的存储器件上 + * + * 如果步骤3无法实施, 但是设备的uuid的确每次都能读到, 而且每次读出来都一样, + * 则可优先用步骤4.a, 即将uuid的信息持久化到flash中, 每次开机优先读这片flash + * 如果4.a无法实现, 则可用4.b, 即每次直接从器件中读取出设备的uuid(器件可能不稳定,不推荐) + * + * 如果步骤3/4都无法实施, 则返回-1作为错误码 + * + * @param[in] buf 缓存的buf, 用以存储设备的唯一标识符 + * @param[in] len 缓存的最大长度. 默认是256 Byte + * + * @return int + * @retval <= 0 没有获取到uuid + * @retval > 0 返回的字节数 + **/ +DLL_HAL_API int HAL_GetUUID(uint8_t *buf, int len); + +#endif /* __IMPORT_PRODUCT_H__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tcp.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tcp.h new file mode 100755 index 000000000..256c378fb --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tcp.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef __IMPORT_TCP_H__ +#define __IMPORT_TCP_H__ + +/** + * @brief Establish a TCP connection. + * + * @param [in] host: @n Specify the hostname(IP) of the TCP server + * @param [in] port: @n Specify the TCP port of TCP server + * + * @return The handle of TCP connection. + @retval 0 : Fail. + @retval > 0 : Success, the value is handle of this TCP connection. + */ +DLL_HAL_API uintptr_t HAL_TCP_Establish(_IN_ const char *host, _IN_ uint16_t port); + +/** + * @brief Destroy the specific TCP connection. + * + * @param [in] fd: @n Specify the TCP connection by handle. + * + * @return The result of destroy TCP connection. + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +DLL_HAL_API int32_t HAL_TCP_Destroy(_IN_ uintptr_t fd); + +/** + * @brief Write data into the specific TCP connection. + * The API will return immediately if 'len' be written into the specific TCP connection. + * + * @param [in] fd @n A descriptor identifying a connection. + * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. + * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * + * @retval < 0 : TCP connection error occur.. + * @retval 0 : No any data be write into the TCP connection in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. + + * @see None. + */ +DLL_HAL_API int32_t HAL_TCP_Write(_IN_ uintptr_t fd, _IN_ const char *buf, _IN_ uint32_t len, _IN_ uint32_t timeout_ms); + +/** + * @brief Read data from the specific TCP connection with timeout parameter. + * The API will return immediately if 'len' be received from the specific TCP connection. + * + * @param [in] fd @n A descriptor identifying a TCP connection. + * @param [out] buf @n A pointer to a buffer to receive incoming data. + * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * + * @retval -2 : TCP connection error occur. + * @retval -1 : TCP connection be closed by remote server. + * @retval 0 : No any data be received in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. + + * @see None. + */ +DLL_HAL_API int32_t HAL_TCP_Read(_IN_ uintptr_t fd, _OU_ char *buf, _OU_ uint32_t len, _IN_ uint32_t timeout_ms); + +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tls.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tls.h new file mode 100755 index 000000000..aa608c27e --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_tls.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_TLS_H__ +#define __IMPORT_TLS_H__ + +#include + +typedef struct { + void *(*malloc)(uint32_t size); + void (*free)(void *ptr); +} ssl_hooks_t; + +DLL_HAL_API int HAL_SSL_Del_KV_Session_Ticket(void); + +/** + * @brief Set malloc/free function. + * + * @param [in] hooks: @n Specify malloc/free function you want to use + * + * @retval < 0 : Fail. + * @retval 0 : Success. + * + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_SSLHooks_set(ssl_hooks_t *hooks); + +/** + * @brief Establish a SSL connection. + * + * @param [in] host: @n Specify the hostname(IP) of the SSL server + * @param [in] port: @n Specify the SSL port of SSL server + * @param [in] ca_crt @n Specify the root certificate which is PEM format. + * @param [in] ca_crt_len @n Length of root certificate, in bytes. + * @return SSL handle. + * @see None. + * @note None. + */ +DLL_HAL_API uintptr_t HAL_SSL_Establish( + _IN_ const char *host, + _IN_ uint16_t port, + _IN_ const char *ca_crt, + _IN_ size_t ca_crt_len); + +/** + * @brief Destroy the specific SSL connection. + * + * @param[in] handle: @n Handle of the specific connection. + * + * @return The result of destroy ssl + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +DLL_HAL_API int32_t HAL_SSL_Destroy(_IN_ uintptr_t handle); + +/** + * @brief Write data into the specific SSL connection. + * The API will return immediately if 'len' be written into the specific SSL connection. + * + * @param [in] handle @n A descriptor identifying a connection. + * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. + * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * @retval < 0 : SSL connection error occur.. + * @retval 0 : No any data be write into the SSL connection in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. + * @see None. + */ +DLL_HAL_API int32_t HAL_SSL_Write(_IN_ uintptr_t handle, _IN_ const char *buf, _IN_ int len, _IN_ int timeout_ms); + +/** + * @brief Read data from the specific SSL connection with timeout parameter. + * The API will return immediately if 'len' be received from the specific SSL connection. + * + * @param [in] handle @n A descriptor identifying a SSL connection. + * @param [out] buf @n A pointer to a buffer to receive incoming data. + * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. + * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. + * + * @retval -2 : SSL connection error occur. + * @retval -1 : SSL connection be closed by remote server. + * @retval 0 : No any data be received in 'timeout_ms' timeout period. + * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. + * @see None. + */ +DLL_HAL_API int32_t HAL_SSL_Read(_IN_ uintptr_t handle, _OU_ char *buf, _OU_ int len, _IN_ int timeout_ms); + +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_udp.h b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_udp.h new file mode 100755 index 000000000..2f67d5ccb --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/imports/iot_import_udp.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IMPORT_UDP_H__ +#define __IMPORT_UDP_H__ + +/** + * @brief Establish a UDP connection. + * + * @param [in] host: @n Specify the hostname(IP) of the UDP server + * @param [in] port: @n Specify the UDP port of UDP server + * + * @retval < 0 : Fail. + * @retval >= 0 : Success, the value is handle of this UDP connection. + * @see None. + */ +DLL_HAL_API intptr_t HAL_UDP_create(_IN_ char *host, _IN_ unsigned short port); + +/** + * @brief Destroy the specific UDP connection. + * + * @param [in] p_socket: @n Specify the UDP connection by handle. + * @return None. + * @see None . + */ +DLL_HAL_API void HAL_UDP_close(_IN_ intptr_t p_socket); + +/** + * @brief Write data into the specific UDP connection. + * + * @param [in] p_socket @n A descriptor identifying a connection. + * @param [in] p_data @n A pointer to a buffer containing the data to be transmitted. + * @param [in] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + + * @retval < 0 : UDP connection error occur. + * @retval [0,datalen ] : The number of bytes sent. + * @see None. + */ +DLL_HAL_API int HAL_UDP_write( + _IN_ intptr_t p_socket, + _IN_ const unsigned char *p_data, + _IN_ unsigned int datalen); + +/** + * @brief Read data from the specific UDP connection by blocked + * + * @param [in] p_socket @n A descriptor identifying a UDP connection. + * @param [in] p_data @n A pointer to a buffer to receive incoming data. + * @param [out] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @return + * + * @retval < 0 : UDP connect error occur. + * @retval = 0 : End of file. + * @retval > 0 : The number of byte read. + * @see None. + */ +DLL_HAL_API int HAL_UDP_read( + _IN_ intptr_t p_socket, + _OU_ unsigned char *p_data, + _OU_ unsigned int datalen); + +/** + * @brief Read data from the specific UDP connection with timeout parameter. + * The API will return immediately if 'datalen' be received from the specific UDP connection. + * + * @param [in] p_socket @n A descriptor identifying a UDP connection. + * @param [out] p_data @n A pointer to a buffer to receive incoming data. + * @param [out] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. + * @param [in] timeouf_ms @n Specify the timeout value in millisecond. In other words, the API block timeout_ms millisecond maximumly. + * + * @retval -4 : UDP connect error occur. + * @retval -3 : The call was interrupted by a signal before any data was read. + * @retval -2 : No any data be received in 'timeout_ms' timeout period. + * @retval -1 : Invalid parameter. + * @retval 0 : End of file. + * @retval (0,datalen] : The number of byte read. + * @see None. + */ +DLL_HAL_API int HAL_UDP_readTimeout( + _IN_ intptr_t p_socket, + _OU_ unsigned char *p_data, + _OU_ unsigned int datalen, + _IN_ unsigned int timeout_ms); + +/** @} */ /* end of platform_network */ +/** @} */ /* end of platform */ + + +/** + * @brief 创建一个本地的UDP socket, 但并不发起任何网络交互 + * + * @param host : UDP的源地址, 如果不指定地址,设为 NULL + * port : UDP的源端口 + * + * @retval -1 : 创建失败 + * @retval 其它 : 创建成功, 返回值是UDP socket的句柄 + */ +DLL_HAL_API intptr_t HAL_UDP_create_without_connect(_IN_ const char *host, _IN_ unsigned short port); + +/** + * @brief 设置UDP socket的目的地址和目的端口 + * + * @param host : UDP的目的地址 + * port : UDP的目的端口 + * + * @retval -1 : 失败 + * @retval 0 : 设置成功 + */ +DLL_HAL_API int HAL_UDP_connect(_IN_ intptr_t sockfd, + _IN_ const char *host, + _IN_ unsigned short port); + + +/** + * @brief 在指定的UDP socket上发送指定缓冲区的指定长度, 阻塞时间不超过指定时长, 且指定长度若发送完需提前返回 + * + * @param sockfd : UDP socket的句柄 + * @param p_remote : 目标网络地址结构体的首地址 + * @param p_data : 被发送的缓冲区起始地址 + * @param datalen: 被发送的数据长度, 单位是字节(Byte) + * @param timeout_ms : 可能阻塞的最大时间长度, 单位是毫秒 + * + * @retval < 0 : 发送过程中出现错误或异常 + * @retval 0 : 在指定的'timeout_ms'时间间隔内, 没有任何数据被成功发送 + * @retval (0, len] : 在指定的'timeout_ms'时间间隔内, 被成功发送的数据长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_UDP_sendto(_IN_ intptr_t sockfd, + _IN_ const NetworkAddr *p_remote, + _IN_ const unsigned char *p_data, + _IN_ unsigned int datalen, + _IN_ unsigned int timeout_ms); + + +/** + * @brief 从指定的UDP句柄接收指定长度数据到缓冲区, 阻塞时间不超过指定时长, 且指定长度若接收完需提前返回, 源地址保存在出参中 + * + * @param fd : UDP socket的句柄 + * @param p_remote : 存放源网络地址的结构体首地址 + * @param p_data : 存放被接收数据的缓冲区起始地址 + * @param datalen : 接收并存放到缓冲区中数据的最大长度, 单位是字节(Byte) + * @param timeout_ms : 可能阻塞的最大时间长度, 单位是毫秒 + * + * @retval < 0 : 接收过程中出现错误或异常 + * @retval 0 : 在指定的'timeout_ms'时间间隔内, 没有任何数据被成功接收 + * @retval (0, len] : 在指定的'timeout_ms'时间间隔内, 被成功接收的数据长度, 单位是字节(Byte) + */ +DLL_HAL_API int HAL_UDP_recvfrom(_IN_ intptr_t sockfd, + _OU_ NetworkAddr *p_remote, + _OU_ unsigned char *p_data, + _IN_ unsigned int datalen, + _IN_ unsigned int timeout_ms); + + +/** + * @brief 在指定的UDP socket上发送加入组播组的请求 + * + * @param sockfd : 指定用来发送组播请求的UDP socket + * @param p_group : 指定需要加入的组播组名字 + * @retval < 0 : 发送过程中出现异常或失败 + * @retval 0 : 发送成功 + */ +DLL_HAL_API int HAL_UDP_joinmulticast(_IN_ intptr_t sockfd, + _IN_ char *p_group); + +/** + * @brief 绑定UDP socket到指定接口,只接收来自该接口的数据包 + * + * @param fd : 指定用来绑定的UDP socket + * @param ifname : 指定用来绑定socket的网络接口名字 + * + * @retval < 0 : 绑定异常或失败 + * @retval 0 : 发送成功 + */ +DLL_HAL_API int HAL_UDP_bindtodevice(_IN_ intptr_t fd, + _IN_ const char *ifname); + +/** + * @brief 销毁指定的UDP socket, 回收资源 + * + * @param sockfd : 将要关闭并销毁的UDP socket + * + * @return 操作的结果 + * @retval < 0 : 操作失败 + * @retval 0 : 操作成功 + */ +DLL_HAL_API int HAL_UDP_close_without_connect(_IN_ intptr_t sockfd); + +#endif diff --git a/code/application/source/sf_app/component/liveMng/inc/iot_export.h b/code/application/source/sf_app/component/liveMng/inc/iot_export.h new file mode 100755 index 000000000..0c16b7d03 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/iot_export.h @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_EXPORT_H__ +#define __IOT_EXPORT_H__ +#if defined(__cplusplus) +extern "C" { +#endif + +#undef being_deprecated +#define being_deprecated + +#ifdef _WIN32 +#if !defined(CC_IS_MINGW32) +#ifdef DLL_IOT_EXPORTS +#define DLL_IOT_API __declspec(dllexport) +#else +#define DLL_IOT_API __declspec(dllimport) +#endif +#else +#define DLL_IOT_API +#endif +#else +#define DLL_IOT_API +#endif + +#include + +#ifndef LINK_VISUAL_ENABLE +#define LINK_VISUAL_ENABLE //only for LV +#endif + +#ifdef LINK_VISUAL_ENABLE +#define REPORT_UUID_ENABLE +#endif + +#ifndef RDA5981A +#ifndef AIOT_AUTHORIZE_ENABLE + // #define AIOT_AUTHORIZE_ENABLE +#endif +#endif + +extern unsigned int g_report_id; +/* From device.h */ +#define PRODUCT_KEY_LEN (20) +#define DEVICE_NAME_LEN (32) +#define DEVICE_ID_LEN (64) +#define DEVICE_SECRET_LEN (64) +#define PRODUCT_SECRET_LEN (64) + +#define LIVING_SDK_VERSION "1.6.6-6" +#define LINKKIT_VERSION "2.3.0" "_FY_" LIVING_SDK_VERSION + +#define MODULE_VENDOR_ID (32) /* Partner ID */ + +#define HOST_ADDRESS_LEN (128) +#define HOST_PORT_LEN (8) +#define CLIENT_ID_LEN (384) /* Enlarge this buffer size due to add token params etc */ +#define USER_NAME_LEN (512) /* Extend length for ID2 */ +#define PASSWORD_LEN (256) /* Extend length for ID2 */ +#define AESKEY_STR_LEN (32) +#define AESKEY_HEX_LEN (128/8) + +typedef enum _IOT_LogLevel { + IOT_LOG_NONE = 0, + IOT_LOG_CRIT, + IOT_LOG_ERROR, + IOT_LOG_WARNING, + IOT_LOG_INFO, + IOT_LOG_DEBUG, +} IOT_LogLevel; + +#define IOTX_CLOUD_REGION_INVALID (-100) +/* region type */ +typedef enum IOTX_CLOUD_REGION_TYPES { + /* Shanghai */ + IOTX_CLOUD_REGION_SHANGHAI, + + /* Singapore */ + IOTX_CLOUD_REGION_SINGAPORE, + + /* Japan */ + IOTX_CLOUD_REGION_JAPAN, + + /* America east*/ + IOTX_CLOUD_REGION_USA_EAST, + + /* Germany */ + IOTX_CLOUD_REGION_GERMANY, + + /* America west*/ + IOTX_CLOUD_REGION_USA_WEST, + + /*Define the valid maximum region id is 19999*/ + IOTX_CLOUD_REGION_MAX = 19999, + + /* Custom setting */ + IOTX_CLOUD_REGION_CUSTOM = 20000, + + /* Maximum number of custom region */ + IOTX_CLOUD_CUSTOM_REGION_MAX +} iotx_cloud_region_types_t; + +typedef struct { + char product_key[PRODUCT_KEY_LEN + 1]; + char device_name[DEVICE_NAME_LEN + 1]; + char device_id[DEVICE_ID_LEN + 1]; + char device_secret[DEVICE_SECRET_LEN + 1]; + char module_vendor_id[MODULE_VENDOR_ID + 1]; +} iotx_device_info_t; + +typedef struct { + uint16_t port; + uint8_t init; + char *host_name; + char *client_id; + char *username; + char *password; + const char *pub_key; + +} iotx_conn_info_t, *iotx_conn_info_pt; + +/* data srutct define for IOTX_IOCTL_SET_SUBDEV_SIGN */ +typedef struct { + int devid; + const char *sign; +} iotx_ioctl_set_subdev_sign_t; + +/* data struct define for IOTX_IOCTL_GET_SUBDEV_LOGIN */ +typedef struct { + int devid; + int status; +} iotx_ioctl_get_subdev_info_t; + +typedef enum { + IOTX_IOCTL_SET_REGION, /* value(int*): iotx_cloud_region_types_t */ + IOTX_IOCTL_GET_REGION, /* value(int*) */ + IOTX_IOCTL_SET_MQTT_DOMAIN, /* value(const char*): point to mqtt domain string */ + IOTX_IOCTL_SET_MQTT_PORT, /* value(int*): point to mqtt port number*/ + IOTX_IOCTL_SET_ENV, /* value(int*): 0 - env is ONLINE; 1 - env is PRE; 2 - env is DAILY*/ + IOTX_IOCTL_SET_HTTP_DOMAIN, /* value(const char*): point to http domain string */ + IOTX_IOCTL_SET_DYNAMIC_REGISTER, /* value(int*): 0 - Disable Dynamic Register, 1 - Enable Dynamic Register */ + IOTX_IOCTL_GET_DYNAMIC_REGISTER, /* value(int*) */ + IOTX_IOCTL_RECV_PROP_REPLY, /* value(int*): 0 - Disable property post reply by cloud; 1 - Enable property post reply by cloud */ + IOTX_IOCTL_RECV_EVENT_REPLY, /* value(int*): 0 - Disable event post reply by cloud; 1 - Enable event post reply by cloud */ + IOTX_IOCTL_SEND_PROP_SET_REPLY, /* value(int*): 0 - Disable send post set reply by devid; 1 - Enable property set reply by devid */ + IOTX_IOCTL_SET_SUBDEV_SIGN, /* value(const char*): only for slave device, set signature of subdevice */ + IOTX_IOCTL_GET_SUBDEV_LOGIN, /* value(int*): 0 - SubDev is logout; 1 - SubDev is login */ + IOTX_IOCTL_QUERY_DEVID, /* value(iotx_linkkit_dev_meta_info_t*): device meta info, only productKey and deviceName is required, ret value is subdev_id or -1 */ +#ifdef REPORT_UUID_ENABLE + IOTX_IOCTL_SET_UUID_ENABLED, /* value(int*): 1 - anti duplicated uuid capability is enabled; 0 - anti duplicated uuid capability is disabled. */ +#endif + IOTX_IOCTL_SEND_EVENT_NOTIFY_REPLY /* value(int*): 0 - Disable send post set reply by devid; 1 - Enable event notify reply by devid */ +} iotx_ioctl_option_t; + +typedef enum { + ITE_AWSS_STATUS, + ITE_CONNECT_SUCC, + ITE_CONNECT_FAIL, + ITE_DISCONNECTED, + ITE_REDIRECT, + ITE_OFFLINE_RESET, + ITE_RAWDATA_ARRIVED, +#ifndef LINK_VISUAL_ENABLE + ITE_SERVICE_REQUEST, +#else + ITE_SERVICE_REQUST, +#endif + ITE_PROPERTY_SET, + ITE_PROPERTY_GET, + ITE_REPORT_REPLY, + ITE_TRIGGER_EVENT_REPLY, + ITE_TIMESTAMP_REPLY, + ITE_TOPOLIST_REPLY, + ITE_TOPO_CHANGE, + ITE_PERMIT_JOIN, + ITE_SUBDEV_MISC_OPS, + ITE_INITIALIZE_COMPLETED, + ITE_FOTA, + ITE_COTA, + ITE_MQTT_CONNECT_SUCC, + ITE_EVENT_NOTIFY, +#ifdef LINK_VISUAL_ENABLE + ITE_LINK_VISUAL, +#endif + ITE_CLOUD_ERROR, + ITE_STATE_EVERYTHING, + ITE_STATE_USER_INPUT, + ITE_STATE_SYS_DEPEND, + ITE_STATE_MQTT_COMM, + ITE_STATE_WIFI_PROV, + ITE_STATE_COAP_LOCAL, + ITE_STATE_HTTP_COMM, + ITE_STATE_OTA, + ITE_STATE_DEV_BIND, + ITE_STATE_SUB_DEVICE, +#ifdef DM_UNIFIED_SERVICE_POST + ITE_UNIFIED_SERVICE_POST, +#endif + + ITE_STATE_DEV_MODEL /* Must be last state relative event */ +} iotx_ioctl_event_t; + +#define IOT_RegisterCallback(evt, cb) iotx_register_for_##evt(cb); +#define DECLARE_EVENT_CALLBACK(evt, cb) DLL_IOT_API int iotx_register_for_##evt(cb); +#define DEFINE_EVENT_CALLBACK(evt, cb) DLL_IOT_API int iotx_register_for_##evt(cb) { \ + if (evt < 0 || evt >= sizeof(g_impl_event_map)/sizeof(impl_event_map_t)) {return -1;} \ + g_impl_event_map[evt].callback = (void *)callback;return 0;} + +DECLARE_EVENT_CALLBACK(ITE_AWSS_STATUS, int (*cb)(int)) +DECLARE_EVENT_CALLBACK(ITE_CONNECT_SUCC, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_CONNECT_FAIL, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_DISCONNECTED, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_REDIRECT, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_OFFLINE_RESET, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_RAWDATA_ARRIVED, int (*cb)(const int, const unsigned char *, const int)) +#ifndef LINK_VISUAL_ENABLE +DECLARE_EVENT_CALLBACK(ITE_SERVICE_REQUEST, int (*cb)(const int, const char *, const int, const char *, const int, + char **, int *)) +#else +DECLARE_EVENT_CALLBACK(ITE_LINK_VISUAL, int (*cb)(const int, const char *, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_SERVICE_REQUST, int (*cb)(const int, const char *, const int, const char *, const int, const char *, const int, + char **, int *)) +#endif +DECLARE_EVENT_CALLBACK(ITE_PROPERTY_SET, int (*cb)(const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_PROPERTY_GET, int (*cb)(const int, const char *, const int, char **, int *)) +DECLARE_EVENT_CALLBACK(ITE_REPORT_REPLY, int (*cb)(const int, const int, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_TRIGGER_EVENT_REPLY, int (*cb)(const int, const int, const int, const char *, const int, + const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_TIMESTAMP_REPLY, int (*cb)(const char *)) +DECLARE_EVENT_CALLBACK(ITE_TOPOLIST_REPLY, int (*cb)(const int, const int, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_TOPO_CHANGE, int (*cb)(const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_SUBDEV_MISC_OPS, int (*cb)(const int, int, const int, const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_PERMIT_JOIN, int (*cb)(const char *, const int)) +DECLARE_EVENT_CALLBACK(ITE_INITIALIZE_COMPLETED, int (*cb)(const int)) +DECLARE_EVENT_CALLBACK(ITE_FOTA, int (*cb)(const int, const char *)) +DECLARE_EVENT_CALLBACK(ITE_COTA, int (*cb)(const int, const char *, int, const char *, const char *, + const char *, const char *)) +DECLARE_EVENT_CALLBACK(ITE_MQTT_CONNECT_SUCC, int (*cb)(void)) +DECLARE_EVENT_CALLBACK(ITE_CLOUD_ERROR, int (*cb)(const int, const char *, const char *)) +DECLARE_EVENT_CALLBACK(ITE_EVENT_NOTIFY, int (*cb)(const int, const char *, const int)) + +#ifdef DM_UNIFIED_SERVICE_POST +DECLARE_EVENT_CALLBACK(ITE_UNIFIED_SERVICE_POST, int (*cb)(const int, const int, const int, const char *, const int)) +#endif + +typedef int (*state_handler_t)(const int state_code, const char *state_message); +DECLARE_EVENT_CALLBACK(ITE_STATE_EVERYTHING, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_USER_INPUT, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_SYS_DEPEND, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_MQTT_COMM, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_WIFI_PROV, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_COAP_LOCAL, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_HTTP_COMM, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_OTA, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_DEV_BIND, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_SUB_DEVICE, state_handler_t cb); +DECLARE_EVENT_CALLBACK(ITE_STATE_DEV_MODEL, state_handler_t cb); + +int iotx_state_event(const int event, const int code, const char *msg_format, ...); +#define dump_user_input_status(...) iotx_state_event(ITE_STATE_USER_INPUT, __VA_ARGS__) +#define dump_sys_depend_status(...) iotx_state_event(ITE_STATE_SYS_DEPEND, __VA_ARGS__) +#define dump_mqtt_status(...) iotx_state_event(ITE_STATE_MQTT_COMM, __VA_ARGS__) +#define dump_awss_status(...) iotx_state_event(ITE_STATE_WIFI_PROV, __VA_ARGS__) +#define dump_coap_lcl_status(...) iotx_state_event(ITE_STATE_COAP_LOCAL, __VA_ARGS__) +#define dump_http_status(...) iotx_state_event(ITE_STATE_HTTP_COMM, __VA_ARGS__) +#define dump_ota_status(...) iotx_state_event(ITE_STATE_OTA, __VA_ARGS__) +#define dump_dev_bind_status(...) iotx_state_event(ITE_STATE_DEV_BIND, __VA_ARGS__) +#define dump_sub_dev_status(...) iotx_state_event(ITE_STATE_SUB_DEVICE, __VA_ARGS__) +#define dump_dev_model_status(...) iotx_state_event(ITE_STATE_DEV_MODEL, __VA_ARGS__) + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_log log + * @{ + */ + +/** + * @brief Set the print level. + * + * @param [in] level: @n level from 1 to 5, the greater the number, the more detailed the printing. + * + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_SetLogLevel(IOT_LogLevel level); + +/** + * @brief Print the memory usage statistics. + * + * @param [in] level: @n level from 1 to 5, the greater the number, the more detailed the printing. + * + * @return None. + * @see None. + */ +DLL_IOT_API void IOT_DumpMemoryStats(IOT_LogLevel level); + +/** @} */ /* end of api_log */ + +/** @defgroup group_api_conninfo conninfo + * @{ + */ + + +/** + * @brief Based on the 'product_key' + 'device_name' + 'device_secret' produce an MQTT connection username and password. + * + * @param [in] product_key: @n Apply for 'product_key' in the AliYun Console. + * @param [in] device_name: @n Apply for 'device_name' in the AliYun Console. + * @param [in] device_secret: @n Apply for 'device_secret' in the AliYun Console. + * @param [out] info_ptr: @n return MQTT connection parameter. + * + * @retval -1 : Fail. + * @retval 0 : Success. + * @see None. + */ +DLL_IOT_API int IOT_SetupConnInfo(const char *product_key, + const char *device_name, + const char *device_secret, + void **info_ptr); + +/** + * @brief Setup Demain type, should be called before MQTT connection. + * + * @param [in] option: see iotx_ioctl_option_t. + * + * @return None. + * @see None. + */ +DLL_IOT_API int IOT_Ioctl(int option, void *data); + +/** @} */ /* end of api_conninfo */ + +/** @} */ /* end of api */ + +#include "exports/iot_export_compat.h" +#include "exports/iot_export_errno.h" +#include "exports/iot_export_awss.h" +#include "exports/iot_export_mqtt.h" +#include "exports/iot_export_shadow.h" +#include "exports/iot_export_coap.h" +#include "exports/iot_export_ota.h" +#include "exports/iot_export_http.h" +#include "exports/iot_export_event.h" +#include "exports/iot_export_http2.h" +#include "exports/iot_export_http2_stream.h" +#include "exports/iot_export_diagnosis.h" +#include "exports/iot_export_guider.h" +#include "exports/iot_export_linkkit.h" +#include "exports/iot_export_reset.h" + +#if defined(__cplusplus) +} +#endif +#endif /* __IOT_EXPORT_H__ */ diff --git a/code/application/source/sf_app/component/liveMng/inc/iot_import.h b/code/application/source/sf_app/component/liveMng/inc/iot_import.h new file mode 100755 index 000000000..21b68c8e2 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/iot_import.h @@ -0,0 +1,537 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOT_IMPORT_H__ +#define __IOT_IMPORT_H__ +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef _WIN32 +#if !defined(CC_IS_MINGW32) +#ifdef DLL_HAL_EXPORTS +#define DLL_HAL_API __declspec(dllexport) +#else +#define DLL_HAL_API __declspec(dllimport) +#endif +#else +#define DLL_HAL_API +#endif +#else +#define DLL_HAL_API +#endif + +#include +#include +#include +#include +#include +#include +#if defined(_PLATFORM_IS_LINUX_) +#include +#endif + +#ifndef _IN_ +#define _IN_ +#endif +#ifndef _OU_ +#define _OU_ +#endif + +#define IOT_TRUE (1) /* indicate boolean value true */ +#define IOT_FALSE (0) /* indicate boolean value false */ + +/** @defgroup group_platform platform + * @{ + */ + +#ifdef SIM7000C_DAM +#include "qapi_ali_iot.h" +#else + +/*********************************** mutex interface ***********************************/ + +/** @defgroup group_platform_mutex mutex + * @{ + */ + +/** + * @brief Create a mutex. + * + * @retval NULL : Initialize mutex failed. + * @retval NOT_NULL : The mutex handle. + * @see None. + * @note None. + */ +DLL_HAL_API void *HAL_MutexCreate(void); + +/** + * @brief Destroy the specified mutex object, it will release related resource. + * + * @param [in] mutex @n The specified mutex. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_MutexDestroy(_IN_ void *mutex); + + + +/** + * @brief Waits until the specified mutex is in the signaled state. + * + * @param [in] mutex @n the specified mutex. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_MutexLock(_IN_ void *mutex); + +/** + * @brief Releases ownership of the specified mutex object.. + * + * @param [in] mutex @n the specified mutex. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_MutexUnlock(_IN_ void *mutex); + +#define PLATFORM_WAIT_INFINITE (~0) + +typedef enum { + os_thread_priority_idle = -3, /* priority: idle (lowest) */ + os_thread_priority_low = -2, /* priority: low */ + os_thread_priority_belowNormal = -1, /* priority: below normal */ + os_thread_priority_normal = 0, /* priority: normal (default) */ + os_thread_priority_aboveNormal = 1, /* priority: above normal */ + os_thread_priority_high = 2, /* priority: high */ + os_thread_priority_realtime = 3, /* priority: realtime (highest) */ + os_thread_priority_error = 0x84, /* system cannot determine priority or thread has illegal priority */ +} hal_os_thread_priority_t; + +typedef struct _hal_os_thread { + hal_os_thread_priority_t priority; /*initial thread priority */ + void *stack_addr; /* thread stack address malloced by caller, use system stack by . */ + size_t stack_size; /* stack size requirements in bytes; 0 is default stack size */ + int detach_state; /* 0: not detached state; otherwise: detached state. */ + char *name; /* thread name. */ +} hal_os_thread_param_t; + +/** + * @brief 按照指定入参创建一个线程 + * + * @param[out] thread_handle @n The new thread handle, memory allocated before thread created and return it, free it after thread joined or exit. + * @param[in] start_routine @n A pointer to the application-defined function to be executed by the thread. + This pointer represents the starting address of the thread. + * @param[in] arg @n A pointer to a variable to be passed to the start_routine. + * @param[in] hal_os_thread_param @n A pointer to stack params. + * @param[out] stack_used @n if platform used stack buffer, set stack_used to 1, otherwise set it to 0. + * @return + @verbatim + = 0: on success. + = -1: error occur. + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_ThreadCreate( + _OU_ void **thread_handle, + _IN_ void *(*work_routine)(void *), + _IN_ void *arg, + _IN_ hal_os_thread_param_t *hal_os_thread_param, + _OU_ int *stack_used); + +/** + * @brief 设置指定的线程为`Detach`状态 + * + * @param[in] thread_handle: pointer to thread handle. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_ThreadDetach(_IN_ void *thread_handle); + +/** + * @brief 杀死指定的线程 + * + * @param[in] thread_handle: pointer to thread handle, NULL means itself + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_ThreadDelete(_IN_ void *thread_handle); + +/** + * @brief 创建一个计数信号量 + * + * @return semaphore handle. + * @see None. + * @note The recommended value of maximum count of the semaphore is 255. + */ +DLL_HAL_API void *HAL_SemaphoreCreate(void); + +/** + * @brief 销毁一个计数信号量, 回收其所占用的资源 + * + * @param[in] sem @n the specified sem. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_SemaphoreDestroy(_IN_ void *sem); + +/** + * @brief 在指定的计数信号量上做自减操作并等待 + * + * @param[in] sem @n the specified semaphore. + * @param[in] timeout_ms @n timeout interval in millisecond. + If timeout_ms is PLATFORM_WAIT_INFINITE, the function will return only when the semaphore is signaled. + * @return + @verbatim + = 0: The state of the specified object is signaled. + = -1: The time-out interval elapsed, and the object's state is nonsignaled. + @endverbatim + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_SemaphoreWait(_IN_ void *sem, _IN_ uint32_t timeout_ms); + +/** + * @brief 在指定的计数信号量上做自增操作, 解除其它线程的等待 + * + * @param[in] sem @n the specified semaphore. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_SemaphorePost(_IN_ void *sem); + +/** @} */ /* end of platform_mutex */ + + +/** @defgroup group_platform_memory_manage memory + * @{ + */ + +/** + * @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. + * + * @param [in] size @n specify block size in bytes. + * @return A pointer to the beginning of the block. + * @see None. + * @note Block value is indeterminate. + */ +DLL_HAL_API void *HAL_Malloc(_IN_ uint32_t size); + +/** + * @brief Changes the size of the memory block pointed to by ptr to size bytes. + * + * @param [in] ptr @n pointer to be realloc + * @param [in] size @n specify block size in bytes for newly allocated memory + * @return A pointer to the beginning of newly allocated memory. + * @see None. + * @note Block value is indeterminate. + */ +DLL_HAL_API void *HAL_Realloc(_IN_ void *ptr, _IN_ uint32_t size); + +/** + * @brief Allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. + * + * @param [in] nmemb @n array elements item counts + * @param [in] size @n specify block size in bytes for every array elements + * @return A pointer to the beginning of allocated memory. + * @see None. + * @note Block value is indeterminate. + */ +DLL_HAL_API void *HAL_Calloc(_IN_ uint32_t nmemb, _IN_ uint32_t size); + +/** + * @brief Deallocate memory block + * + * @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Free(_IN_ void *ptr); + + +/** @} */ /* end of platform_memory_manage */ + +/** @defgroup group_platform_other other + * @{ + */ + +/** + * @brief Retrieves the number of milliseconds that have elapsed since the system was boot. + * + * @return the number of milliseconds. + * @see None. + * @note None. + */ +DLL_HAL_API uint64_t HAL_UptimeMs(void); + +/** + * @brief Retrieves the timer string. + * + * @param [buf] give buffer to save timer string + * @param [len] the length of buffer + * @return the string of timer. + * @see None. + * @note None. + */ +DLL_HAL_API char *HAL_GetTimeStr(_IN_ char *buf, _IN_ int len); + +/** + * @brief Sleep thread itself. + * + * @param [in] ms @n the time interval for which execution is to be suspended, in milliseconds. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_SleepMs(_IN_ uint32_t ms); + +/** + * @brief Set seed for a sequence of pseudo-random integers, which will be returned by HAL_Random() + * + * @param [in] seed @n A start point for the random number sequence + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Srandom(_IN_ uint32_t seed); + +/** + * @brief Get a random integer + * + * @param [in] region @n Range of generated random numbers + * @return Random number + * @see None. + * @note None. + */ +DLL_HAL_API uint32_t HAL_Random(_IN_ uint32_t region); + +/** + * @brief Writes formatted data to stream. + * + * @param [in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers + that specifies how subsequent arguments are converted for output. + * @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Printf(_IN_ const char *fmt, ...); + +/** + * @brief Writes formatted data to string. + * + * @param [out] str: @n String that holds written text. + * @param [in] len: @n Maximum length of character will be written + * @param [in] fmt: @n Format that contains the text to be written, it can optionally contain embedded format specifiers + that specifies how subsequent arguments are converted for output. + * @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. + * @return bytes of character successfully written into string. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Snprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, ...); + +/** + * @brief Writes formatted data to string. + * + * @param [out] str: @n String that holds written text. + * @param [in] len: @n Maximum length of character will be written. + * @param [in] fmt: @n Format that contains the text to be written. + * @param [in] ap: @n the variable argument list. + * @return bytes of character successfully format into string. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Vsnprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, _IN_ va_list ap); + +/** @} */ /* end of group_platform_other */ + +/** @defgroup group_platform_network network + * @{ + */ + +#define NETWORK_ADDR_LEN (16) /* IP网络地址的长度 */ +#define HAL_MAC_LEN (17 + 1) /* MAC地址的长度 */ + +typedef struct _network_addr_t { + unsigned char + addr[NETWORK_ADDR_LEN]; /* 目标UDP主机地址, 点分十进制IP地址 */ + unsigned short port; /* 目标UDP端口, 范围是0-65535 */ +} NetworkAddr; + +/** + * @brief 获取Wi-Fi网口的MAC地址, 格式应当是"XX:XX:XX:XX:XX:XX" + * + * @param mac_str : 用于存放MAC地址字符串的缓冲区数组 + * @return 指向缓冲区数组起始位置的字符指针 + */ +DLL_HAL_API char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]); + +/** + * @brief 获取Wi-Fi网口的IP地址, 点分十进制格式保存在字符串数组出参, 二进制格式则作为返回值, 并以网络字节序(大端)表达 + * + * @param ifname : 指定Wi-Fi网络接口的名字 + * @param ip_str : 存放点分十进制格式的IP地址字符串的数组 + * @return 二进制形式的IP地址, 以网络字节序(大端)组织 + */ +DLL_HAL_API uint32_t HAL_Wifi_Get_IP(_OU_ char ip_str[NETWORK_ADDR_LEN], _IN_ const char *ifname); + +/** + * @brief check system network is ready(get ip address) or not. + * + * @param None. + * @return 0, net is not ready; 1, net is ready. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Sys_Net_Is_Ready(); + +/** + * @brief reboot system immediately. + * + * @param None. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_Reboot(void); + +DLL_HAL_API void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data); +DLL_HAL_API int HAL_Timer_Start(void *t, int ms); +DLL_HAL_API int HAL_Timer_Stop(void *t); +DLL_HAL_API int HAL_Timer_Delete(void *timer); + +/** + * @brief Set the UTC time in milliseconds. + * + * @param[in] ms: @the time value to be set in milliseconds. + * @return None. + * @see None. + * @note None. + */ +DLL_HAL_API void HAL_UTC_Set(long long ms); + +/** + * @brief Get the UTC time in milliseconds. + * + * @param None. + * @return the UTC time in milliseconds. + * @see None. + * @note None. + */ +DLL_HAL_API long long HAL_UTC_Get(void); + +typedef enum { + HAL_SEEK_SET, + HAL_SEEK_CUR, + HAL_SEEK_END +} hal_fs_seek_type_t; + +/** + * @brief Opens the file whose name is specified in the parameter filename and associates it + * with a stream that can be identified in future operations by the void pointer returned. + * + * @param [in] path: @n The file path to open.With reference to fopen + * @param [in] mode: @n C string containing a file access mode. + * @return If the file is successfully opened, the function returns a pointer to void object that can be used to + * identify the stream on future operations.Otherwise, a null pointer is returned. + * @see None. + * @note None. + */ +DLL_HAL_API void *HAL_Fopen(const char *path, const char *mode); +/** + * @brief Reads an array of count elements, each one with a size of size bytes, from the stream and + * stores them in the block of memory specified by ptr. + * + * @param [in] buff: @n Pointer to a block of memory with a size of at least (size*count) bytes, converted to a void*. + * @param [in] size: @n size in bytes, of each element to be read. + * @param [in] count: @n Number of elements, each one with a size of size bytes. + * @param [in] stream: @n Pointer to void that specifies an input stream. + * @return The total number of elements successfully read is returned.If either size or count is zero, the function returns zero + * @see None. + * @note None. + */ +DLL_HAL_API uint32_t HAL_Fread(void *buff, uint32_t size, uint32_t count, void *stream); + +/** + * @brief Writes an array of count elements, each one with a size of size bytes, from the block of memory pointed + * by ptr to the current position in the stream. + * + * @param [in] ptr: @n Pointer to the array of elements to be written, converted to a const void*. + * @param [in] size: @n Size in bytes of each element to be written. + * @param [in] count: @n Number of elements, each one with a size of size bytes. + * @param [in] stream: @n Pointer to void that specifies an output stream. + * @return The total number of elements successfully written is returned.If either size or count is zero, the function returns zero. + * @see None. + * @note None. + */ +DLL_HAL_API uint32_t HAL_Fwrite(const void *ptr, uint32_t size, uint32_t count, void *stream); + +/** + * @brief Sets the position indicator associated with the stream to a new position. + * + * @param [in] stream: @n Pointer to void that identifies the stream. + * @param [in] offset: @n Binary files: Number of bytes to offset from origin. + * @param [in] origin: @n Position used as reference for the offset. It is specified by one of value enum in hal_fs_seek_type_t. + * + * @return If successful, the function returns zero.Otherwise, it returns non-zero value. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Fseek(void *stream, long offset, int origin); + +/** + * @brief Closes the file associated with the stream and disassociates it. + * + * @param [in] stream: @n Pointer to void that identifies the stream. + * + * @return If the stream is successfully closed, a zero value is returned.On failure, non-zero is returned. + * @see None. + * @note None. + */ +DLL_HAL_API int HAL_Fclose(void *stream); + +/** + * @brief Returns the current value of the position indicator of the stream. + * + * @param [in] stream: @n Pointer to void that identifies the stream. + * + * @return On success, the current value of the position indicator is returned.On failure, -1L is returned. + * @see None. + * @note None. + */ +DLL_HAL_API long HAL_Ftell(void *stream); + +#include "iot_export.h" +#include "imports/iot_import_config.h" +#include "imports/iot_import_product.h" +#include "imports/iot_import_crypt.h" +#include "imports/iot_import_awss.h" +#include "imports/iot_import_dtls.h" +#include "imports/iot_import_tls.h" +#include "imports/iot_import_tcp.h" +#include "imports/iot_import_udp.h" +#include "imports/iot_import_ota.h" +#include "imports/iot_import_kv.h" + +/*for compatible with older version*/ +#define HAL_Kv_Set aos_kv_set +#define HAL_Kv_Get aos_kv_get +#define HAL_Kv_Del aos_kv_del +#define HAL_Kv_Del_By_Prefix aos_kv_del_by_prefix + +#endif /* SIM7000C_DAM */ +#if defined(__cplusplus) +} +#endif +#endif /* __IOT_IMPORT_H__ */ + diff --git a/code/application/source/sf_app/component/liveMng/inc/link_visual_api.h b/code/application/source/sf_app/component/liveMng/inc/link_visual_api.h new file mode 100755 index 000000000..64563ac4e --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/link_visual_api.h @@ -0,0 +1,412 @@ +#ifndef LINK_VISUAL_API_H +#define LINK_VISUAL_API_H + +#include "link_visual_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------——-- SDK业务相关的消息通知 ----------------------------*/ +/** +* @brief SDK需要发送消息(一般指MQTT) +* +* @param [IN] lv_message_publish_param_s: 消息上报参数 +* +* @retval < 0 : Fail. +* @retval 0 : Success. +* +*/ +typedef int (*lv_message_publish_cb)(const lv_message_publish_param_s *message); + +/** + * @brief 通知设备开始推流 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_start_push_stream_param_s: 开始推流的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + * + * @notice: type == LV_STREAM_CMD_LIVE时,需要调用lv_stream_send_video()/lv_stream_send_audio()直接开始推流; + * type == LV_STREAM_CMD_STORAGE_RECORD_BY_FILE/LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME时, + * 需要等待lv_on_push_streaming_cmd_cb()中的消息通知;当lv_on_push_streaming_cmd_cb()中通知LV_STORAGE_RECORD_START时, + * 调用lv_stream_send_video()/lv_stream_send_audio()开始推流 + * @see lv_stream_start_service() lv_on_push_streaming_cmd_cb() + */ +typedef int (*lv_start_push_streaming_cb)(const lv_device_auth_s *auth, const lv_start_push_stream_param_s *param); + +/** + * @brief 通知设备停止推流 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_stop_push_stream_param_s: 停止推流的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_stop_push_streaming_cb)(const lv_device_auth_s *auth, const lv_stop_push_stream_param_s *param); + +/** + * @brief 推送直播/存储录像流的过程中,需要支持的命令 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_on_push_streaming_cmd_param_s: 推流过程中的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_on_push_streaming_cmd_cb)(const lv_device_auth_s *auth, const lv_on_push_stream_cmd_param_s *param); + +/** + * @brief 对接过程中,收到的数据 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_on_push_streaming_data_param_s: 推流过程中的参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_on_push_streaming_data_cb)(const lv_device_auth_s *auth, const lv_on_push_streaming_data_param_s *param); + +/** + * @brief 查询存储录像列表 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_query_record_param_s: 录像查询参数 + * + * @return void + */ +typedef void (*lv_query_record_cb)(const lv_device_auth_s *auth, const lv_query_record_param_s *param); + +/** + * @brief 主动 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_query_record_param_s: 录像查询参数 + * + * @return void + */ +typedef void (*lv_trigger_picture_cb)(const lv_device_auth_s *auth, const lv_trigger_picture_param_s *param); + +/** + * @brief 云端事件通知 + * + * @param [IN] type: 事件类型 + * @param [IN] param: 事件附加参数 + * + * @retval < 0 : Fail. + * @retval 0 : Success. + */ +typedef int (*lv_cloud_event_cb)(const lv_device_auth_s *auth, const lv_cloud_event_param_s *param); + +/** + * @brief 功能强校验 + * @notice 请按照实际的功能对接情况进行返回: + * 预录功能已经实现时,返回LV_SDK_FEATURE_CHECK_PRE_EVENT;否则返回LV_SDK_FEATURE_CHECK_CLOSE + * + * + * @retval LV_FEATURE_CHECK_PRE_EVENT : 预录功能已实现. + * @retval LV_FEATURE_CHECK_CLOSE : 预录功能未实现 + */ +typedef int (*lv_feature_check_cb)(void); + +/** + * @brief 日志信息回调 + * + * @param [IN] level : 日志级别 + * @param [IN] file_name : 日志的源文件名称 + * @param [IN] line : 日志的源文件行数 + * @param [IN] fmt : 日志打印可变参数 + * + * @return void + */ +typedef void (*lv_log_cb)(lv_log_level_e level, const char *file_name, int line, const char *fmt, ...); + +/*-------------------------SDK配置相关内容----------------------------*/ +#define PATH_NAME_LEN (32) + +/* 配置类参数结构体 */ +typedef struct { + /* 设备类型设置: + * 1. 单IPC设备,device_type = 0, + * 2. NVR+IPC设备,device_type = 1; + * NOTICE:请查看结构体 lv_device_auth_s: + * device_type = 0时,只接受一个dev_id = 0的设备(IPC) + * device_type = 1时,只接受一个dev_id = 0的设备(NVR),接受不超过sub_num个dev_id > 0的设备(IPC) */ + unsigned int device_type; + /* 最大子设备数量配置 */ + /* device_type = 0时,sub_num不生效;device_type = 1时,取值范围:[1,128] */ + unsigned int sub_num; + + /* SDK的日志配置 */ + lv_log_level_e log_level; + lv_log_destination log_dest; + + /* 点播源在多客户端观看时,无论是云端转发还是P2P,客户端观看的码流都是独立的,不会进行分发 + * storage_record_source_solo_num为单设备最大点播路数, + * storage_record_source_solo_num值范围[1,8],默认值为1 + * storage_record_source_num为支持的点播最大路数;路数越多,网络带宽、内存占用越高 + * storage_record_source_num值范围[storage_record_source_solo_num, 256],该参数仅对NVR生效 + * */ + unsigned int storage_record_source_solo_num; + unsigned int storage_record_source_num; + + /* + * lv_post_intelligent_alarm/lv_post_alarm_image/lv_post_trigger_picture会对图片数据进行拷贝(如有), + * image_size_max用于设置总的图片拷贝内存值,单位:B。 + * 若单张图片超过总内存限制,则直接丢弃图片;若单张图片超过剩余内存限制,则从旧到新丢弃图片,直至新图片可被拷贝。丢弃后的行为见具体API。 + * */ + unsigned int image_size_max; + /* + * lv_post_intelligent_alarm/lv_post_alarm_image/lv_post_trigger_picture会异步上传图片, + * image_parallel用于设置图片并发上传数量,值范围[1,8]。 + * 并发越大,发送越快,内存消耗越高,带宽占用越大。WIFI设备建议为[2,3],有线IPC建议为[2,4],有线NVR建议为[4,8] + * */ + unsigned int image_parallel; + + /* 码流自检查功能,能帮助开发者发现码流本身问题,调试过程中请打开。 + * 0 - 关闭, >0 - 打开 */ + unsigned int stream_auto_check; + /* 码流数据自动保存功能,需要排查码流兼容性等问题才需要打开,在stream_auto_check打开后可使用 + * 0 - 关闭, >0 - 打开 */ + unsigned int stream_auto_save; + /* 码流数据自动保存的路径,路径需保证存在且可写,路径名末尾需要含有"/",如 "/tmp/" */ + char stream_auto_save_path[PATH_NAME_LEN + 1]; + + /* 设备取证服务功能(Device Attestation Service, 缩写为das),0-开启,1-关闭 */ + unsigned int das_close; + + /* + * DNS服务器配置 + * @Notice: dns_mode的值 + * = LV_DNS_SYSTEM:仅读取系统配置/etc/resolv.conf中的DNS服务器配置 + * = LV_DNS_EXTERNAL:仅读取外部配置dns_num和dns_servers中的DNS服务器配置 + * = LV_DNS_SYSTEM_AND_EXTERNAL:读取系统配置和外部配置 + * @Notice: + * 若未成功读取到DNS服务器配置,则使用内置的IP: 223.5.5.5/223.6.6.6/8.8.8.8 + * 总读取到的DNS配置不超过10个(系统配置优先/按读取顺序) + * 推荐使用LV_DNS_SYSTEM_AND_EXTERNAL,除系统自动获取的DNS配置外,外部另配置数个公共、可靠的服务器;推荐总配置3个以上 + * */ + lv_dns_mode_e dns_mode; + unsigned int dns_num; + char **dns_servers;//字符串数组 +} lv_init_config_s; + +/* 回调类参数结构体 */ +typedef struct { + /* 消息通道 */ + lv_message_publish_cb message_publish_cb; + + /* SDK的日志回调(如有) */ + lv_log_cb log_cb; + + /* 音视频推流服务 */ + lv_start_push_streaming_cb start_push_streaming_cb; + lv_stop_push_streaming_cb stop_push_streaming_cb; + lv_on_push_streaming_cmd_cb on_push_streaming_cmd_cb; + lv_on_push_streaming_data_cb on_push_streaming_data_cb; + + /* 存储录像查询命令 */ + lv_query_record_cb query_storage_record_cb; + + /* 主动抓图命令 */ + lv_trigger_picture_cb trigger_picture_cb; + + /* 云端事件通知 */ + lv_cloud_event_cb cloud_event_cb; + + /* 功能强校验 */ + lv_feature_check_cb feature_check_cb; +} lv_init_callback_s; + +/* 配置参数结构体 */ +typedef struct { + int todo; +} lv_init_system_s; + +/*------------------------- SDK功能接口 ----------------------------*/ +/** + * @brief SDK初始化 + * + * @param [IN] config: SDK配置参数集合 + * @param [IN] callback: SDK回调参数集合 + * @param [IN] system: SDK系统参数集合 + * + * @return lv_error_e + */ +int lv_init(const lv_init_config_s *config, const lv_init_callback_s *callback, const lv_init_system_s *system); + +/** + * @brief SDK销毁 + * + * @param [IN] void + * + * @return lv_error_e + */ +int lv_destroy(void); + +/** + * @brief 消息适配器,将消息注入该函数中,由SDK代为处理 + * + * @param [IN] lv_device_auth_s: 设备认证信息 + * @param [IN] lv_message_adapter_property_s: 消息内容入参 + * + * @return lv_error_e + */ +int lv_message_adapter(const lv_device_auth_s *auth, const lv_message_adapter_param_s *param); + +/** + * @brief 在发送实际视音频数据前发送视音频相关配置,用于直播推流和存储录像播放 + * + * @param [IN] service_id: 服务ID,来自回调 lv_start_push_streaming_cb + * @param [IN] lv_stream_send_config_param_s: 配置参数集合 + * @notice 通知开始推流、强制I帧请求后,需要调用此API。 + * + * @return lv_error_e + * @see lv_start_push_streaming_cb() + */ +int lv_stream_send_config(int service_id, const lv_stream_send_config_param_s *param); + +/** + * @brief 发送音视频数据 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_stream_send_media_param_s: 音视频参数 + * + * @return lv_error_e + */ +int lv_stream_send_media(int service_id, const lv_stream_send_media_param_s *param); + +/** + * @brief 卡录像点播模式时(LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME),在最后一个文件播放结束后调用 + * 含预录事件录像功能时(LV_STREAM_CMD_PRE_EVENT_RECORD),在预录缓冲数据消耗完第一次切换为实时码流时调用 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_push_stream_cmd_s: 命令名 + * + * @return lv_error_e + * + */ +int lv_stream_send_cmd(int service_id, lv_push_stream_cmd_s cmd); + +/** + * @brief 智能报警事件图片上传,通过该接口上报的图片和事件是绑定在一起的 + * + * @param [IN] param: 结构体lv_intelligent_alarm_param_s指针 + * + * @notice: + * 1. 调用间隔短于云端设定值,返回失败 + * 2. 附加字符串大于2048B时会被截断,但不会返回失败 + * 3. 单张图片数据最大为5MB(含),超过则返回失败 + * 4. 本接口为异步接口,存在图片数据时,SDK会进行图片数据的拷贝,拷贝受到image_size_max的限制; + * 5. 事件也会进行拷贝,不受限制。事件和图片随后加入任务队列中 + * 6. 任务队列遵循FIFO进行处理,并发处理量为image_parallel + * 7. 任务处理时,先上传图片。如果有图片数据,则进行图片上传,否则进入下一步。如果图片上传失败,不会进行重传,进入下一步 + * 8. 上报事件,如果事件上报失败,不会进行重传。 + * + * @return lv_error_e + */ +int lv_post_intelligent_alarm(const lv_device_auth_s *auth, const lv_intelligent_alarm_param_s *param, int *service_id); + +/** + * @brief 报警事件图片上传或抓图上传,通过该接口上报的图片和事件是绑定在一起的 + * @notice 报警事件上传时,推荐使用lv_post_intelligent_alarm,该接口将逐渐废弃 + + * @notice: + * 1. 调用间隔短于云端设定值,返回失败 + * 2. 附加字符串大于2048B时会被截断,但不会返回失败 + * 3. 单张图片数据最大为5MB(含),超过则返回失败 + * 4. 本接口为异步接口,存在图片数据时,SDK会进行图片数据的拷贝,拷贝受到image_size_max的限制; + * 5. 事件也会进行拷贝,不受限制。事件和图片随后加入任务队列中 + * 6. 任务队列遵循FIFO进行处理,并发处理量为image_parallel + * 7. 任务处理时,先上传事件。若事件上传失败,不会进行重传 + * 8. 上传图片。如果有图片数据,则进行图片上传,否则不做操作。如果图片上传失败,不会进行重传 + * + * + * @return lv_error_e + * @see lv_trigger_pic_capture_cb() + */ +int lv_post_alarm_image(const lv_device_auth_s *auth, const lv_alarm_event_param_s *param, int *service_id); + +/** + * @brief 卡录像查询回复 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_query_record_response_s: 回复内容 + * + * @return lv_error_e + * + */ +int lv_post_query_record(int service_id, const lv_query_record_response_param_s *response); + +/** + * @brief 抓图回复 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_trigger_picture_response_param_s: 回复内容 + * + * @notice: + * 1. 本接口为异步接口,存在图片数据时,SDK会进行图片数据的拷贝,拷贝受到image_size_max的限制; + * 2. 图片上传随后加入任务队列中 + * 3. 任务队列遵循FIFO进行处理,并发处理量为image_parallel + * 4. 上传图片。如果有图片数据,则进行图片上传,否则不做操作。如果图片上传失败,不会进行重传 + * + * @return lv_error_e + * + */ +int lv_post_trigger_picture(int service_id, const lv_trigger_picture_response_param_s *response); + + +/** + * @brief 云端事件回复 + * + * @param [IN] service_id: 服务ID + * @param [IN] lv_cloud_event_response_param_s: 回复内容 + * + * + * @notice: + * 目前仅 LV_CLOUD_EVENT_DELETE_FILE 需要回复 + * + * @return lv_error_e + * + */ +int lv_post_cloud_event(int service_id, const lv_cloud_event_response_param_s *response); + +/* + * @brief 用于动态调节SDK的某些功能,如日志级别,方便调试。 + * + * @param [IN] type: 功能类型,见enum lv_control_type_e. + * @param [IN] ...: 可变长参数,参数类型与功能类型有关 + * type:LV_CONTROL_LOG_LEVEL, 参数:int log_level;实时生效 + * type:LV_CONTROL_STREAM_AUTO_CHECK,参数:unsigned int flag;已启动的流不会生效,新启动的流会生效 + * type:LV_CONTROL_STREAM_AUTO_SAVE,参数:unsigned int flag,char *save_path;需要关闭时, + * save_path参数不会被使用。已启动的流不会生效,新启动的流会生效 + * + * @return lv_error_e + */ +int lv_control(lv_control_type_e type, ...); + +/* + * @brief 部分SDK功能在编译阶段不存在问题,但在运行阶段会出现问题。 + * SDK要触发此类功能,一般需要云端配合,调试复杂。 + * 该接口可在开发阶段即触发功能调试 + * + * @notice 调用该接口,未出现LV-ERROR/LV_WARN级别日志即可 + * + * @param [IN] type: 功能类型,见enum lv_develop_test_type_e. + * @param [IN] ...: 可变长参数,参数类型与功能类型有关,具体参考sample + * type:LV_DEVELOP_TEST_PING, 参数:unsigned int times ,const char *address; + * + * @notice 未避免此函数被滥用,SDK会限制调用次数为3次,重新初始化SDK即可重置次数 + * + * + * @return lv_error_e + */ +int lv_develop_test(lv_develop_test_type_e type, ...); + + +#ifdef __cplusplus +} +#endif +#endif /* LINK_VISUAL_API_H */ diff --git a/code/application/source/sf_app/component/liveMng/inc/link_visual_enum.h b/code/application/source/sf_app/component/liveMng/inc/link_visual_enum.h new file mode 100755 index 000000000..8d613d522 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/link_visual_enum.h @@ -0,0 +1,275 @@ +#ifndef LINK_VISUAL_ENUM_H_ +#define LINK_VISUAL_ENUM_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + LV_STORAGE_RECORD_PLAN = 0, //计划录像 + LV_STORAGE_RECORD_ALARM = 1, //报警录像 + LV_STORAGE_RECORD_INITIATIVE = 2, // 主动录像 + LV_STORAGE_RECORD_ANY = 99, //所有类型。 +} lv_storage_record_type_e; //如果不在这个范围内,则为用户自定义录像类型,由APP和设备侧自主协商含义,SDK不再明确列出具体类型. + +typedef enum { + LV_STREAM_CMD_LIVE = 0, //直播 + /* + * @NOTICE: + * 点播时(LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME/LV_STREAM_CMD_STORAGE_RECORD_BY_FILE), + * 时间戳和发流速率应严格按照推荐的方式值发送,发帧速度建议: + * 全帧倍数(<4倍): + * 按照实际播放速度*1.1系数来发帧,例如:视频文件帧率是25fps,每帧时间戳pts间隔差应稳定在40ms, 建议发帧速率:1/2倍为13fps、1倍为27fps、2倍为55fps。 + * + * 抽帧倍数(>=4倍): + * 抽帧倍数播放只需要发送I帧,按照实际播放速度*1.1系数来发帧,例如:视频文件帧率是25fps,GOP大小为50,即I帧pts间隔差值为2S,建议发I帧速率:4倍为2.2fps、8倍为4.4fps、16倍为8.8fps。 + * + * */ + LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME = 2,//按UTC时间播放设备存储录像 + LV_STREAM_CMD_PRE_EVENT_RECORD = 3,//事件录像(预录),LV_SDK_FEATURE_CHECK_PRE_EVENT打开时才会回调 + LV_STREAM_CMD_VOICE = 4,//对讲 + LV_STREAM_CMD_CLOUD_STORAGE = 5,//云存储,目前暂不可用 + LV_STREAM_CMD_STORAGE_RECORD_BY_FILE = 6,//按文件名播放设备存储录像 + LV_STREAM_CMD_PERFORMANCE = 7,//开发者无需处理 + LV_STREAM_CMD_MAX, +} lv_stream_cmd_type_e; + +typedef enum { + LV_QUERY_RECORD_BY_DAY = 0,//查询当天的录像 + LV_QUERY_RECORD_BY_MONTH,//查询当月的录像 +} lv_query_record_type_e; + +/* 收到来自远程的指令 */ +typedef enum { + LV_STORAGE_RECORD_START = 0,//开始播放,对于录像点播有效 + LV_STORAGE_RECORD_PAUSE,//暂停,对于录像点播有效 + LV_STORAGE_RECORD_UNPAUSE,// 继续播放,对于录像点播有效 + LV_STORAGE_RECORD_SEEK,// 定位,对于录像点播有效 + LV_STORAGE_RECORD_STOP,//停止,对于录像点播有效 + LV_STORAGE_RECORD_SET_PARAM,//设置点播倍速等参数信息 + LV_LIVE_REQUEST_I_FRAME,//强制编码I帧,对于直播有效 + LV_VOICE_DATA, +} lv_on_push_streaming_cmd_type_e; + +/* 发送给远程的指令 */ +typedef enum { + LV_STORAGE_RECORD_COMPLETE,//录像点播已经播放完成 + LV_PRE_EVENT_RECORD_COMPLETE,//事件录像的预录数据已经完成 +} lv_push_stream_cmd_s; + +/* 视频格式 */ +typedef enum { + // 编码类型切换后需保证首帧为I帧 + LV_VIDEO_FORMAT_H264 = 0, //AVC + LV_VIDEO_FORMAT_H265 = 1, //HEVC +} lv_video_format_e; + +/* 音频格式 */ +typedef enum { + //不支持同一设备切换音频编码类型,不支持切换编码参数 + LV_AUDIO_FORMAT_PCM = 0,//音频对讲功能不支持PCM + LV_AUDIO_FORMAT_G711A = 1, + LV_AUDIO_FORMAT_AAC = 2, + LV_AUDIO_FORMAT_G711U = 3, +} lv_audio_format_e; + +/* 音频采样率 */ +typedef enum { + LV_AUDIO_SAMPLE_RATE_96000 = 0, + LV_AUDIO_SAMPLE_RATE_88200 = 1, + LV_AUDIO_SAMPLE_RATE_64000 = 2, + LV_AUDIO_SAMPLE_RATE_48000 = 3, + LV_AUDIO_SAMPLE_RATE_44100 = 4, + LV_AUDIO_SAMPLE_RATE_32000 = 5, + LV_AUDIO_SAMPLE_RATE_24000 = 6, + LV_AUDIO_SAMPLE_RATE_22050 = 7, + LV_AUDIO_SAMPLE_RATE_16000 = 8, + LV_AUDIO_SAMPLE_RATE_12000 = 9, + LV_AUDIO_SAMPLE_RATE_11025 = 10, + LV_AUDIO_SAMPLE_RATE_8000 = 11, + LV_AUDIO_SAMPLE_RATE_7350 = 12, +} lv_audio_sample_rate_e; + +/* 音频位宽 */ +typedef enum { + LV_AUDIO_SAMPLE_BITS_8BIT = 0, + LV_AUDIO_SAMPLE_BITS_16BIT = 1, +} lv_audio_sample_bits_e; + +/* 音频声道 */ +typedef enum { + LV_AUDIO_CHANNEL_MONO = 0, + LV_AUDIO_CHANNEL_STEREO = 1, +} lv_audio_channel_e; + +/* 媒体封装或编码类型 */ +typedef enum { + LV_MEDIA_JPEG = 0, + LV_MEDIA_PNG, +} lv_media_format; + +/* 事件类型 */ +typedef enum { + /* 普通事件 */ + LV_EVENT_MOVEMENT = 1, //移动侦测 + LV_EVENT_SOUND = 2, //声音侦测 + LV_EVENT_HUMAN = 3, //人形侦测 + LV_EVENT_PET = 4, //宠物侦测 + LV_EVENT_CROSS_LINE = 5, //越界侦测 + LV_EVENT_REGIONAL_INVASION = 6, //区域入侵侦测 + LV_EVENT_FALL = 7, //跌倒检测 + LV_EVENT_FACE = 8, //人脸检测 + LV_EVENT_SMILING = 9, //笑脸检测 + LV_EVENT_ABNORMAL_SOUND = 10, //异响侦测 + LV_EVENT_CRY = 11, //哭声侦测 + LV_EVENT_LAUGH = 12, //笑声侦测 + LV_EVENT_MAX +} lv_event_type_e; + +/* 智能事件类型 */ +typedef enum { + LV_INTELLIGENT_EVENT_MOVING_CHECK = 1,//移动侦测 + LV_INTELLIGENT_EVENT_SOUND_CHECK = 2,//声音侦测 + LV_INTELLIGENT_EVENT_HUMAN_CHECK = 3,//人形侦测 + LV_INTELLIGENT_EVENT_PET_CHECK = 4,//宠物侦测 + LV_INTELLIGENT_EVENT_CROSS_LINE_CHECK = 5,//越界侦测 + LV_INTELLIGENT_EVENT_REGIONAL_INVASION = 6,//区域入侵侦测 + LV_INTELLIGENT_EVENT_FALL_CHECK = 7,//跌倒检测 + LV_INTELLIGENT_EVENT_FACE_CHECK = 8,//人脸检测 + LV_INTELLIGENT_EVENT_SMILING_CHECK = 9,//笑脸检测 + LV_INTELLIGENT_EVENT_ABNORMAL_SOUND_CHECK = 10,//异响侦测 + LV_INTELLIGENT_EVENT_CRY_CHECK = 11,//哭声侦测 + LV_INTELLIGENT_EVENT_LAUGH_CHECK = 12,//笑声侦测 + LV_INTELLIGENT_EVENT_ILLEGAL_PARKING = 10001,//违章停车 + LV_INTELLIGENT_EVENT_ILLEGAL_SALE = 10002,//占道经营 + LV_INTELLIGENT_EVENT_MOTORCYCLE_RECOGNITION = 10003,//摩托车识别 + LV_INTELLIGENT_EVENT_PEDESTRIAN_RECOGNITION = 10004,//行人识别 + LV_INTELLIGENT_EVENT_VEHICLES_RECOGNITION = 10005,//车辆识别 + LV_INTELLIGENT_EVENT_DELIVER_SALE = 10006,//到店经营 + LV_INTELLIGENT_EVENT_FACE_RECOGNITION = 10007,//人脸识别 + LV_INTELLIGENT_EVENT_FACE_DETECT = 10008,//人脸检测 + LV_INTELLIGENT_EVENT_PERSON_VEHICLE_DETECTION = 10009,//人车检测 + LV_INTELLIGENT_EVENT_IPC_OCCLUSION_DETECTION = 10010,//摄像头遮挡检测 + LV_INTELLIGENT_EVENT_IPC_MOVE_DETECTION = 10011,//摄像头移动检测 + LV_INTELLIGENT_EVENT_KEY_AREA_OCCUPY = 10012,//重点区域占用 + LV_INTELLIGENT_EVENT_REGIONAL_INVASION_GW = 11001,//区域入侵 + LV_INTELLIGENT_EVENT_CLIMBING_DETECT = 11002,//攀高检测 + LV_INTELLIGENT_EVENT_ARISE_DETECT = 11003,//起身检测 + LV_INTELLIGENT_EVENT_ABSENT_DETECT = 11004,//离岗检测 + LV_INTELLIGENT_EVENT_LOITERING_DETECT = 11005,//人员逗留检测 + LV_INTELLIGENT_EVENT_CROSS_LINE_DETECT = 11006,//拌线检测 + LV_INTELLIGENT_EVENT_RETROGRADE_DETECT = 11007,//逆行检测 + LV_INTELLIGENT_EVENT_QUICKLY_MOVING = 11008,//快速移动 + LV_INTELLIGENT_EVENT_GOODS_MOVED = 11009,//物品移动 + LV_INTELLIGENT_EVENT_GOODS_LEFT = 11010,//物品遗留 + LV_INTELLIGENT_EVENT_CROWD_DENSITY = 11011,//人群密度估计 + LV_INTELLIGENT_EVENT_CROWD_GATHERED = 11012,//人群聚集 + LV_INTELLIGENT_EVENT_CROWD_DISPERSED = 11013,//人群发散 + LV_INTELLIGENT_EVENT_STRENUOUS_EXERCISE = 11014,//剧烈运动 + LV_INTELLIGENT_EVENT_FALL_DETECT = 11015,//跌倒检测 + LV_INTELLIGENT_EVENT_KID_TRACK = 11016,//小孩防走失 + LV_INTELLIGENT_EVENT_MASK_DETECT = 11017,//口罩识别 + LV_INTELLIGENT_EVENT_PET_DETECT = 11018,//宠物检测 + LV_INTELLIGENT_EVENT_HUMAN_BODY_FACE_DETECT = 11022,//人体人脸检测 + LV_INTELLIGENT_EVENT_ELECTRICAL_BICYCLE_DETECT = 11023,//电瓶车识别 + LV_INTELLIGENT_EVENT_FALLING_OBJECTS_DETECT = 11027,//高空抛物检测 + LV_INTELLIGENT_EVENT_ILLEGAL_NON_MOTOR_VEHICLE_PARKING = 12001,//非机动车乱停 + LV_INTELLIGENT_EVENT_GARBAGE_EXPOSURE = 12002,//垃圾暴露 + LV_INTELLIGENT_EVENT_HANGING_ALONG_THE_STREET = 12003,//沿街晾挂 + LV_INTELLIGENT_EVENT_FIRE_DETECT = 13001,//火灾检测 + LV_INTELLIGENT_EVENT_FIRE_CHANNEL_OCCUPANCY = 13002,//消防通道占用 + LV_INTELLIGENT_EVENT_SMOKE_DETECT = 13003,//吸烟检测 + LV_INTELLIGENT_EVENT_PASSENGER_FLOW = 14001,//客流统计 +} lv_intelligent_event_type_e; + +/* 云端事件类型 */ +typedef enum { + LV_CLOUD_EVENT_MASK = 0,//检测口罩 + LV_CLOUD_EVENT_DOWNLOAD_FILE = 1,//下载文件 + LV_CLOUD_EVENT_UPLOAD_FILE = 2,//上传文件 + LV_CLOUD_EVENT_DELETE_FILE = 3,//删除文件 +} lv_cloud_event_type_e; + +/* SDK日志等级 */ +typedef enum { + LV_LOG_ERROR = 2, + LV_LOG_WARN = 3, + LV_LOG_INFO = 4, + LV_LOG_DEBUG = 5, + LV_LOG_VERBOSE = 6, + LV_LOG_MAX = 7, +} lv_log_level_e; + +/* SDK日志输出定向*/ +typedef enum { + LV_LOG_DESTINATION_FILE,//写文件,未实现;需写文件请使用 LV_LOG_DESTINATION_USER_DEFINE + LV_LOG_DESTINATION_STDOUT,//直接向stdout输出日志 + LV_LOG_DESTINATION_USER_DEFINE,//将日志消息放入回调函数 lv_log_cb 中。可在回调函数中实现写文件功能。 + LV_LOG_DESTINATION_MAX +} lv_log_destination; + +/* SDK的函数返回值枚举量 */ +typedef enum { + LV_WARN_BUF_FULL = 1, + LV_ERROR_NONE = 0, + LV_ERROR_DEFAULT = -1, + LV_ERROR_ILLEGAL_INPUT = -2, +} lv_error_e; + +/* 远程文件类型 */ +typedef enum { + LV_REMOTE_FILE_OTHERS = 0, + LV_REMOTE_FILE_VOICE_RECORD = 1, + LV_REMOTE_FILE_FACE_PICTURE = 2, +} lv_remote_file_type_e ; + +/* 消息适配器类型 */ +typedef enum { + LV_MESSAGE_ADAPTER_TYPE_TSL_PROPERTY = 0, //物模型属性消息,目前未使用 + LV_MESSAGE_ADAPTER_TYPE_TSL_SERVICE, //物模型服务消息 + LV_MESSAGE_ADAPTER_TYPE_LINK_VISUAL, // LinkVisual自定义消息 + LV_MESSAGE_ADAPTER_TYPE_CONNECTED, //上线信息 +} lv_message_adapter_type_s; + +/* SDK控制类型 */ +typedef enum { + LV_CONTROL_LOG_LEVEL = 0, + LV_CONTROL_STREAM_AUTO_CHECK, + LV_CONTROL_STREAM_AUTO_SAVE, +} lv_control_type_e; + +/* SDK控制类型 */ +typedef enum { + LV_DEVELOP_TEST_PING,//用于验证SDK能否完成PING功能 +} lv_develop_test_type_e; + +/* 流的媒体数据类型 */ +typedef enum { + LV_STREAM_MEDIA_VIDEO = 0, + LV_STREAM_MEDIA_AUDIO, +} lv_stream_media_type_e; + +/* dns的服务器类型 */ +typedef enum { + LV_DNS_SYSTEM = 0, + LV_DNS_EXTERNAL = 1, + LV_DNS_SYSTEM_AND_EXTERNAL = 2, +} lv_dns_mode_e; +/* dns的服务器类型 */ +typedef enum { + SF_PARAM_MAINSTREAM = 0, + SF_PARAM_SUBSTREAM = 1, + SF_PARAM_VOICE = 2, + SF_PARAM_STORAGE_RECORD_BY_UTC_TIME, + SF_PARAM_STORAGE_RECORD_BY_FILE, + SF_PARAM_BUTT +} SF_PARAM_VIDEO_AUDIO_e; + +#ifdef __cplusplus +} +#endif + +#endif // LINK_VISUAL_ENUM_H_ diff --git a/code/application/source/sf_app/component/liveMng/inc/link_visual_struct.h b/code/application/source/sf_app/component/liveMng/inc/link_visual_struct.h new file mode 100755 index 000000000..990b65c66 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/link_visual_struct.h @@ -0,0 +1,262 @@ +#ifndef LINK_VISUAL_STRUCT_H +#define LINK_VISUAL_STRUCT_H + +#include "link_visual_enum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* 消息上报参数 */ +typedef struct { + char *topic;//消息主键 + char *message;//消息体 + int qos;//消息的服务质量(quality of service) + int dev_id; +} lv_message_publish_param_s; + +/* 设备认证信息 */ +typedef struct { + int dev_id;//0-主设备,>0-子设备,<0-illegal + char *product_key; + char *device_name; + char *device_secret; +} lv_device_auth_s; + +/* 视频参数结构体 */ +typedef struct { + lv_video_format_e format; //视频编码格式 + unsigned int fps; //帧率 + unsigned int key_frame_interval_ms;//最大关键帧间隔时间,单位:毫秒 + unsigned int duration;//按LV_STREAM_CMD_STORAGE_RECORD_BY_FILE时的文件时长,单位s +} lv_video_param_s; + +/* 音频参数结构体 */ +typedef struct { + lv_audio_format_e format; + lv_audio_sample_rate_e sample_rate; + lv_audio_sample_bits_e sample_bits; + lv_audio_channel_e channel; +} lv_audio_param_s; + +typedef struct { + /* + * bitrate_kbps为目标码率,单位为kbps; + * SDK根据码流来预设定内部视音频缓冲区,设置过大会导致弱网下延迟增大,设置过小会导致弱网时丢帧频繁,画面卡顿 + * 内存分配大小:[0,1000) : 128KB ; [1000,2048) : 256KB ; [2048,4096) : 512KB ; [4096,6000) : 1MB ; [6144,∞) : 2MB; + * */ + unsigned int bitrate_kbps; + lv_video_param_s *video_param;//视频的相关参数配置 + lv_audio_param_s *audio_param;//音频的相关参数配置 +} lv_stream_send_config_param_s; + +typedef struct { + struct { + lv_stream_media_type_e type; + unsigned int len; + unsigned int timestamp_ms; + char *p; + } common; + struct { + lv_video_format_e format; + int key_frame; + } video; + struct { + lv_audio_format_e format; + } audio; +} lv_stream_send_media_param_s; + +/* 开始推流参数 */ +typedef struct { + struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 + } common; + struct { + int stream_type;//主、子码流等 + } live; + struct { + int pre_time;//预录事件录像的预录时间 + } pre; + struct { + unsigned int start_time;//播放当天0点的UTC时间,单位:s + unsigned int stop_time;//播放当天24点的UTC时间,单位:s + unsigned int seek_time;//播放的UTC时间相对于start_time的相对时间,即 seek_time + start_time = 播放的utc时间,单位:s + lv_storage_record_type_e record_type;//录像类型 + } by_utc; + struct { + int stream_type;//主、子码流等 + } cloud; + struct { + int empty;//无作用的参数 + } voice; + struct { + unsigned int seek_time;//播放的时间相对于文件起始的相对时间 + char *file_name;//要点播的文件名 + } by_file; +} lv_start_push_stream_param_s; + +/* 结束推流参数 */ +typedef struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 +} lv_stop_push_stream_param_s; + +typedef struct { + struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 + lv_on_push_streaming_cmd_type_e cmd_type;//命令类型 + } common; + struct { + unsigned int timestamp_ms;//seek的时间戳,单位:ms. + } seek; + struct { + unsigned int speed;//倍速信息 + unsigned int key_only;//0-推送全数据帧,1-仅推送I帧 + } set_param; +} lv_on_push_stream_cmd_param_s; + +typedef struct { + int service_id;//服务ID + lv_stream_cmd_type_e stream_cmd_type;//推流命令类型 + unsigned int len; + unsigned int timestamp; + lv_audio_param_s *audio_param; + char *p; +} lv_on_push_streaming_data_param_s; + +typedef struct { + struct { + int service_id;//服务ID + lv_query_record_type_e type;//查询类型 + } common; + struct { + lv_storage_record_type_e type;//路线类型 + unsigned int start_time;//查询的开始时间,UTC时间,秒数 + unsigned int stop_time;//查询的结束时间,UTC时间,秒数 + unsigned int num; //录像查询的数量,等于0的时候 请求时间范围内的全部录像 + } by_day; + struct { + char* month;//查询的年月份,如201806 + } by_month; +} lv_query_record_param_s; + +typedef struct { + unsigned int start_time; // 录像开始时间,UTC时间,单位为秒 + unsigned int stop_time; // 录像结束时间,UTC时间,单位为秒 + unsigned int file_size; // 录像的文件大小,单位字节 + char *file_name; // 录像的文件名 + lv_storage_record_type_e record_type; //录像类型 +} lv_query_record_response_day; //结构体数组 + +/* 录像查询列表结构体 */ +typedef struct { + struct { + unsigned int num; //录像数量,days数组的长度 + lv_query_record_response_day *days; // + } by_day; + struct { + int *months; //months为int数组,长度为31.int值为0表示无录像,非0表示有录像,当前月份不足31天部分也置为0(如2月30) + } by_month; +} lv_query_record_response_param_s; + +/* 抓图回复结构体 */ +typedef struct { + char *p;//报警事件的媒体数据,不大于1MB(大于时会返回错误),为空时仅上传其他信息 + unsigned int len; +} lv_trigger_picture_response_param_s; + +/* 消息适配器内容 */ +typedef struct { + lv_message_adapter_type_s type; + char *msg_id; + unsigned int msg_id_len; + char *service_name; + unsigned int service_name_len; + char *request; + unsigned int request_len; +} lv_message_adapter_param_s; + +typedef struct { + int service_id;//服务ID +} lv_trigger_picture_param_s; + +typedef struct { + int service_id;//服务ID + lv_cloud_event_type_e event_type; + /* 口罩识别事件 */ + struct { + void *reserved; + } mask; + /* 文件下载事件 */ + struct { + lv_remote_file_type_e file_type; + unsigned int file_size; + char *file_name; + char *url; + char *md5; + } file_download; + struct { + lv_remote_file_type_e file_type; + char *file_name; + char *url; + } file_upload; + struct { + char *file_name; + } file_delete; +} lv_cloud_event_param_s; + +typedef struct { + int result;//1-成功,!=1 -失败 + char *reason;//失败时的原因字符串 +} lv_cloud_event_response_param_s; + +/* 智能事件参数集 */ +typedef struct { + lv_intelligent_event_type_e type;//智能事件类型 + lv_media_format format;//智能事件的媒体数据类型,当前只支持图片类 + struct { + char *p; + unsigned int len; + } media;//智能事件的媒体数据,不大于1MB(大于时会返回错误),为空时仅上传其他信息 + struct { + char *p; + unsigned int len; + } addition_string;//智能事件的附加字符串信息,不大于2048B(大于时会截断),为空时仅上传其他信息 +} lv_intelligent_alarm_param_s; + +/* 报警事件参数集 */ +typedef struct { + lv_event_type_e type; + struct { + char *p; + unsigned int len; + } media; //报警事件的媒体数据,不大于1MB(大于时会返回错误),为空时仅上传其他信息 + struct { + char *p; + unsigned int len; + } addition_string;//告警内容,格式为字符串;不大于1024个字节,超过会被截断;若物模型里AlarmEvent里无data字段,p传NULL即可;若有data字段但不需要使用,p则传空字符串 +} lv_alarm_event_param_s; + +/* 功能强校验类型 */ +typedef enum { + LV_FEATURE_CHECK_CLOSE = 0,//被检验功能是关闭的 + /* + * 直播预建联功能说明: + * 在APP等准备开始观看时(例如APP进入到了设备列表页面),建立直播连接,此时仅交互少量心跳数据 + * APP开始观看时,正式发送音视频数据; + * 该功能能够提高首帧的速度 + * NOTICE: APP需要同时打开预建联功能; + * NOTICE: V2.1.6开始支持该功能,若打开了预建联功能,不能降级成不支持预建联的SDK(V2.1.6之前的版本) + * 0 - 关闭, >0 - 打开 + * */ + LV_FEATURE_CHECK_LIVE_PRE_PUBLISH = 1000,//支持功能:直播预建联功能 + LV_FEATURE_CHECK_PRE_EVENT = 10000,//支持功能:预录事件录像 +} lv_feature_check_e ; + +#ifdef __cplusplus +} +#endif + +#endif //LINK_VISUAL_STRUCT_H diff --git a/code/application/source/sf_app/component/liveMng/inc/linkkit_client.h b/code/application/source/sf_app/component/liveMng/inc/linkkit_client.h new file mode 100755 index 000000000..fcb1f8ddb --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/linkkit_client.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef PROJECT_LINKKIT_DEMO_H +#define PROJECT_LINKKIT_DEMO_H + +#include "link_visual_struct.h" +#include "iot_export_linkkit.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * 文件用于描述linkkit的启动、结束过程,以及linkkit生命周期过程中对命令的收发处理 + */ + +/* linkkit支持一型一密模式,即通过product_key/product_secret/device_name获取到device_secret */ +//#define LINKKIT_DYNAMIC_REGISTER + +/* linkkit支持实例化 */ +//#define LINKKIT_INSTANCE + +/* ali-smartliving-sdk-c功能 */ +#define SMARTLIVING + +/* linkkit资源初始化,并连接服务器 */ +int linkkit_client_start(const iotx_linkkit_dev_meta_info_t *main, + unsigned int sub_num, const iotx_linkkit_dev_meta_info_t *sub); + +/* linkkit与服务器断开连接,并释放资源 */ +void linkkit_client_destroy(); + +int linkkit_message_publish_cb(const lv_message_publish_param_s *param); + +/* 属性设置回调 */ +void linkkit_client_set_property_handler(const lv_device_auth_s *auth, const char *value); +void GetAuth(int dev_id, lv_device_auth_s *auth); + + +#if defined(__cplusplus) +} +#endif +#endif //PROJECT_LINKKIT_DEMO_H diff --git a/code/application/source/sf_app/component/liveMng/inc/linkvisual_client.h b/code/application/source/sf_app/component/liveMng/inc/linkvisual_client.h new file mode 100755 index 000000000..2f1ceca0b --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/linkvisual_client.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef PROJECT_LINKVISUAL_DEMO_H +#define PROJECT_LINKVISUAL_DEMO_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "sdk_assistant.h" +#include "link_visual_enum.h" + +/** +* 文件用于描述LinkVisual的启动、结束过程,以及生命周期过程中对音视频的传输过程 +*/ +extern int StreamServiceID; +/* linkvisual资源初始化 */ +int linkvisual_client_init(unsigned int device_type, int sub_num, lv_log_level_e log_level); + +/* linkvisual资源销毁 */ +void linkvisual_client_destroy(); + +int linkvisual_client_assistant_start(unsigned int device_type, const lv_device_auth_s *main, unsigned int sub_num, const lv_device_auth_s *sub); + +void linkvisual_client_assistant_stop(); + +/* 来自IPC的视频帧数据回调 */ +int linkvisual_client_video_handler(int service_id, lv_video_format_e format, unsigned char *buffer, unsigned int buffer_size, + unsigned int present_time, int nal_type); + +/* 来自IPC的音频帧数据回调 */ +int linkvisual_client_audio_handler(int service_id, + lv_audio_format_e format, + unsigned char *buffer, + unsigned int buffer_size, + unsigned int present_time); + +/* 来自IPC的报警图片数据回调 */ +void linkvisual_client_picture_handler(const lv_device_auth_s *auth, unsigned char *buffer, unsigned int buffer_size); + + +/* 来自IPC的点播命令回调 */ +int linkvisual_client_vod_handler(int service_id, int vod_cmd, int param); + +/* 来自IPC的录像列表查询回调 */ +void linkvisual_client_query_record(int service_id, const lv_query_record_response_param_s* param); + +/* 调试过程中使用,可以读取交互式命令,改变部分SDK的行为,可改变的行为请参考:lv_control_type_e */ +void linkvisual_client_control_test(); + +#if defined(__cplusplus) +} +#endif +#endif // PROJECT_LINKVISUAL_DEMO_H \ No newline at end of file diff --git a/code/application/source/sf_app/component/liveMng/inc/sdk_assistant.h b/code/application/source/sf_app/component/liveMng/inc/sdk_assistant.h new file mode 100755 index 000000000..03a606aee --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/sdk_assistant.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#ifndef PROJECT_SDK_ASSISTANT_H +#define PROJECT_SDK_ASSISTANT_H + +#include "link_visual_struct.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* 模拟IPC功能开关,该宏包含的内容都是模拟IPC生产流的功能,开发者集成到设备时需要删除宏内容并修改为实际IPC的功能 */ +//#define DUMMY_IPC + +#define string_safe_copy(target, source, max_len) \ + do { \ + if (target && source && max_len) \ + memcpy(target, source, (strlen(source) > max_len)?max_len:strlen(source));\ +} while(0) + + +lv_device_auth_s *lvDeviceAuthCopy(const lv_device_auth_s *auth, unsigned int num); + +void lvDeviceAuthDelete(lv_device_auth_s *auth, unsigned int num); + +unsigned int lvDeviceAuthCompares(const lv_device_auth_s *auth_1, unsigned int num, const lv_device_auth_s *auth_2); + +#if defined(__cplusplus) +} +#endif + +#endif //PROJECT_SDK_ASSISTANT_H diff --git a/code/application/source/sf_app/component/liveMng/inc/sf_liveMng.h b/code/application/source/sf_app/component/liveMng/inc/sf_liveMng.h new file mode 100755 index 000000000..1eead0dd7 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/inc/sf_liveMng.h @@ -0,0 +1,30 @@ +#ifndef _SF_LIVEMNG_H_ +#define _SF_LIVEMNG_H_ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +typedef struct sf_ARG_ATTR_S { + int dev_id; + char filename[10]; + char filepath[20]; + + +}SF_ARG_ATTR_S; + + +int sf_ipc_live_init(); +void sf_ipc_live_deinit(); +int sf_ipc_httpsNet_init(void); +int sf_ipc_live_writeStream(char *pu8Addr,UINT32 u32Len,UINT32 TimeStamp,UINT8 key_frame); +void sf_venc_stream_start(); +void sf_venc_stream_stop(); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // _DCF_H_ \ No newline at end of file diff --git a/code/application/source/sf_app/component/liveMng/src/BAKMakefile b/code/application/source/sf_app/component/liveMng/src/BAKMakefile new file mode 100755 index 000000000..2dbfee3fb --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/BAKMakefile @@ -0,0 +1,25 @@ +ifneq ($(CROSS_COMPILE),) +CROSS-COMPILE:=$(CROSS_COMPILE) +endif + +ifeq ($(CC),cc) +CC:=$(CROSS-COMPILE)gcc +endif +LD:=$(CROSS-COMPILE)ld + +QL_CM_SRC=linkkit_client.c linkvisual_client.c sdk_assistant.c sf_live.c +H_INCLUDES := \ + -l../../inc \ + -l../inc/exports \ + -l../inc/imports \ + -l../inc +release: + $(CC) -Wall -s ${QL_CM_SRC} $(H_INCLUDES) -o sf_live -lpthread -ldl + +debug: clean + $(CC) -Wall -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM -lpthread -ldl + + +clean: + rm -rf quectel-CM *~ + rm -rf quectel-qmi-proxy diff --git a/code/application/source/sf_app/component/liveMng/src/Makefile b/code/application/source/sf_app/component/liveMng/src/Makefile new file mode 100755 index 000000000..2dbfee3fb --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/Makefile @@ -0,0 +1,25 @@ +ifneq ($(CROSS_COMPILE),) +CROSS-COMPILE:=$(CROSS_COMPILE) +endif + +ifeq ($(CC),cc) +CC:=$(CROSS-COMPILE)gcc +endif +LD:=$(CROSS-COMPILE)ld + +QL_CM_SRC=linkkit_client.c linkvisual_client.c sdk_assistant.c sf_live.c +H_INCLUDES := \ + -l../../inc \ + -l../inc/exports \ + -l../inc/imports \ + -l../inc +release: + $(CC) -Wall -s ${QL_CM_SRC} $(H_INCLUDES) -o sf_live -lpthread -ldl + +debug: clean + $(CC) -Wall -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM -lpthread -ldl + + +clean: + rm -rf quectel-CM *~ + rm -rf quectel-qmi-proxy diff --git a/code/application/source/sf_app/component/liveMng/src/linkkit_client.c b/code/application/source/sf_app/component/liveMng/src/linkkit_client.c new file mode 100755 index 000000000..49c6c3fa6 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/linkkit_client.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include "linkkit_client.h" + +#include + +#include "link_visual_api.h" +#include "link_visual_enum.h" +#include "iot_export_linkkit.h" +#include "iot_export.h" +#include "iot_import.h" +//#include "cJSON.h" +#include "sdk_assistant.h" + + +static int g_master_dev_id = -1; +static int g_running = 0; +static void *g_thread = NULL; +static int g_thread_not_quit = 0; +static int g_connect = 0; + + +static void *g_sub_thread = NULL; +static int g_sub_thread_not_quit = 0; +static void *g_sem = NULL; +static unsigned int g_sub_num = 0;//保存子设备的信息 +static iotx_linkkit_dev_meta_info_t *g_sub = NULL; + +static iotx_linkkit_dev_meta_info_t *g_master_dev_info = NULL; + +/* 这个字符串数组用于说明LinkVisual需要处理的物模型服务 */ +static char *link_visual_service[] = { + "TriggerPicCapture",//触发设备抓图 + "StartVoiceIntercom",//开始语音对讲 + "StopVoiceIntercom",//停止语音对讲 + "StartVod",//开始录像观看 + "StartVodByTime",//开始录像按时间观看 + "StopVod",//停止录像观看 + "QueryRecordTimeList",//查询录像列表 + "QueryRecordList",//查询录像列表 + "StartP2PStreaming",//开始P2P直播 + "StartPushStreaming",//开始直播 + "StopPushStreaming",//停止直播 + "QueryMonthRecord",//按月查询卡录像列表 +}; + +/* 以下两个extern的函数在linkkit或者ali-smartliving中定义 */ +extern int iotx_dm_get_triple_by_devid(int devid, char **product_key, char **device_name, char **device_secret); +extern int iotx_dm_subdev_query(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], + _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], + _OU_ int *devid); +void GetAuth(int dev_id, lv_device_auth_s *auth) { + if (dev_id > 0) { + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + char *product_key = NULL; + char *device_name = NULL; + char *device_secret= NULL; + iotx_dm_get_triple_by_devid(dev_id, &product_key, &device_name, &device_secret); + auth->dev_id = dev_id; + auth->product_key = product_key; + auth->device_name = device_name; + auth->device_secret = device_secret; + } else if (dev_id == 0) { + /* Notice:这里本应该也使用iotx_dm_get_triple_by_devid进行查询,方便代码统一。 + * 但此函数查询devid=0时,会丢失掉device_secret数据(有bug) + * 此处改为直接使用主设备的三元组信息,不进行查询 */ + auth->dev_id = dev_id; + auth->product_key = g_master_dev_info->product_key; + auth->device_name = g_master_dev_info->device_name; +#ifdef LINKKIT_DYNAMIC_REGISTER + HAL_GetDeviceSecret(g_master_dev_info->device_secret); +#endif + auth->device_secret = g_master_dev_info->device_secret; + } +} + + +static void *sub_online(void *args) { + while (g_running) { + HAL_SemaphoreWait(g_sem, PLATFORM_WAIT_INFINITE);//无限等待 + if (!g_running) {//方便退出 + break; + } + + printf("Start login sub dev\n"); + for (unsigned int i = 0; i < g_sub_num; i++) { + iotx_linkkit_dev_meta_info_t meta; + memset(&meta, 0, sizeof(iotx_linkkit_dev_meta_info_t)); + string_safe_copy(meta.product_key, g_sub[i].product_key, PRODUCT_KEY_MAXLEN - 1); + string_safe_copy(meta.device_name, g_sub[i].device_name, DEVICE_NAME_MAXLEN - 1); + string_safe_copy(meta.device_secret, g_sub[i].device_secret, DEVICE_SECRET_MAXLEN - 1); + string_safe_copy(meta.product_secret, g_sub[i].product_secret, PRODUCT_SECRET_MAXLEN - 1); + int devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_SLAVE, &meta); + if (devid == FAIL_RETURN) { + printf("subdev open Failed\n"); + break; + } + + int res = IOT_Linkkit_Connect(devid); + if (res == FAIL_RETURN) { + printf("subdev connect Failed\n"); + break; + } + + res = IOT_Linkkit_Report(devid, ITM_MSG_LOGIN, NULL, 0); + if (res == FAIL_RETURN) { + printf("subdev login Failed\n"); + break; + } + + // 子设备上线消息同步给LinkVisual + lv_device_auth_s auth; + GetAuth(devid, &auth); + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_CONNECTED; + lv_message_adapter(&auth, &in); + + //所有IPC子设备需要上线后上报IPC的属性 + //dummy_ipc_get_all_property(&auth); + } + } + + g_sub_thread_not_quit = 0; + return NULL; +} + +static int user_connected_event_handler(void) { + printf("Cloud Connected\n"); + g_connect = 1; + + /** + * Linkkit连接后,上报设备的属性值。 + * 当APP查询设备属性时,会直接从云端获取到设备上报的属性值,而不会下发查询指令。 + * 对于设备自身会变化的属性值(存储使用量等),设备可以主动隔一段时间进行上报。 + */ + lv_device_auth_s auth; + GetAuth(0, &auth);//这个回调只有主设备才会进入 + + + /* Linkkit连接后,查询下ntp服务器的时间戳,用于同步服务器时间。查询结果在user_timestamp_reply_handler中 */ + IOT_Linkkit_Query(g_master_dev_id, ITM_MSG_QUERY_TIMESTAMP, NULL, 0); + + // linkkit上线消息同步给LinkVisual + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_CONNECTED; + lv_message_adapter(&auth, &in); + + /* 含子设备时,主设备上线后,逐个上线子设备;当网络等原因导致主设备反复上下线时,也需要重新上线子设备 */ + if (g_sub_num && g_sub) { + HAL_SemaphorePost(g_sem); + } + + return 0; +} + +static int user_disconnected_event_handler(void) { + printf("Cloud Disconnected\n"); + g_connect = 0; + + return 0; +} + +static int user_service_request_handler(const int devid, const char *id, const int id_len, + const char *serviceid, const int serviceid_len, + char *request, const int request_len, + char **response, int *response_len) { + printf("user_service_request_handler:Service Request Received, Devid: %d, ID %.*s, Service ID: %.*s, Payload: %s\n", + devid, id_len, id, serviceid_len, serviceid, request); + + /* 部分物模型服务消息由LinkVisual处理,部分需要自行处理。 */ + int link_visual_process = 0; + for (unsigned int i = 0; i < sizeof(link_visual_service)/sizeof(link_visual_service[0]); i++) { + /* 这里需要根据字符串的长度来判断 */ + if (!strncmp(serviceid, link_visual_service[i], strlen(link_visual_service[i]))) { + link_visual_process = 1; + break; + } + } + + if (link_visual_process) { + /* ISV将某些服务类消息交由LinkVisual来处理,不需要处理response */ + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + lv_device_auth_s auth; + GetAuth(devid, &auth); + + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_TSL_SERVICE; + in.msg_id = (char *)id; + in.msg_id_len = id_len; + in.service_name = (char *)serviceid; + in.service_name_len = serviceid_len; + in.request = (char *)request; + in.request_len = request_len; + int ret = lv_message_adapter(&auth, &in); + if (ret < 0) { + printf("LinkVisual process service request failed, ret = %d\n", ret); + return -1; + } + } + else { + /* 非LinkVisual处理的消息示例 */ + *response = "{\"Data\":\"lican\",\"sifar_p2p\":\"are you ok?\"}"; + *response_len = strlen("{\"Data\":\"lican\",\"sifar_p2p\":\"are you ok?\"}"); + } + + return 0; +} + +static int user_property_set_handler(const int devid, const char *request, const int request_len) { + printf("Property Set Received, Devid: %d, Request: %s\n", devid, request); + +#ifdef DUMMY_IPC + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + lv_device_auth_s auth; + GetAuth(devid, &auth); + + cJSON *root = cJSON_Parse(request); + if (!root) { + printf("value parse error\n"); + return -1; + } + cJSON *child = root->child; + + /* 设置属性 */ + if (child->type == cJSON_Number) { + char value[32] = {0}; + snprintf(value, 32, "%d", child->valueint); + dummy_ipc_set_property(&auth, child->string, value); + } else if (child->type == cJSON_String) { + dummy_ipc_set_property(&auth, child->string, child->valuestring); + } + + cJSON_Delete(root); + +#endif // DUMMY_IPC + return 0; +} + +static int user_timestamp_reply_handler(const char *timestamp) { + printf("Current Timestamp: %s \n", timestamp);//时间戳为字符串格式,单位:毫秒 + + return 0; +} + +static int user_fota_handler(int type, const char *version) { + char buffer[1024] = {0}; + int buffer_length = 1024; + + if (type == 0) { + printf("New Firmware Version: %s\n", version); + + IOT_Linkkit_Query(g_master_dev_id, ITM_MSG_QUERY_FOTA_DATA, (unsigned char *)buffer, buffer_length); + } + + return 0; +} + +static int user_event_notify_event_handler(const int devid, const char *request, const int request_len) { + printf("Event Notify Received, Devid: %d, Request: %s \n", devid, request); + return 0; +} + +static int user_link_visual_handler(const int devid, const char *service_id, + const int service_id_len, const char *payload, + const int payload_len) +{ + + printf("payload = [%s]\n",payload); + /* Linkvisual自定义的消息,直接全交由LinkVisual来处理 */ + if (payload == NULL || payload_len == 0) { + return 0; + } + + /* 此处请注意:需要使用devid准确查询出实际的三元组 */ + lv_device_auth_s auth; + GetAuth(devid, &auth); + + lv_message_adapter_param_s in = {0}; + in.type = LV_MESSAGE_ADAPTER_TYPE_LINK_VISUAL; + in.service_name = (char *)service_id; + in.service_name_len = service_id_len; + in.request = (char *)payload; + in.request_len = payload_len; + int ret = lv_message_adapter(&auth, &in); + if (ret < 0) { + printf("LinkVisual process service request failed, ret = %d\n", ret); + return -1; + } + + return 0; +} + +static void *user_dispatch_yield(void *args) { + while (g_running) { + IOT_Linkkit_Yield(10); + } + + g_thread_not_quit = 0; + return NULL; +} + +int linkkit_client_start(const iotx_linkkit_dev_meta_info_t *main, + unsigned int sub_num, const iotx_linkkit_dev_meta_info_t *sub) { + printf("Before start linkkit\n"); + + if (g_running) { + printf("Already running\n"); + return 0; + } + g_running = 1; + + if (!main) { + printf("Illegal input\n"); + return -1; + } + + //存储子设备信息,异步使用 + if (sub_num && sub) { + g_sub_num = sub_num; + g_sub = (iotx_linkkit_dev_meta_info_t *)malloc(sizeof(iotx_linkkit_dev_meta_info_t) *sub_num); + if (!g_sub) { + return -1; + } + memcpy(g_sub, sub, sizeof(iotx_linkkit_dev_meta_info_t) * sub_num); + g_sem = HAL_SemaphoreCreate();//信号量用于线程上线子设备,也可以条件变量、定时器实现等 + if (!g_sem) { + return -1; + } + g_sub_thread_not_quit = 1; + if (HAL_ThreadCreate(&g_sub_thread, sub_online, NULL, NULL, NULL) != 0) { + printf("HAL_ThreadCreate Failed\n"); + g_thread_not_quit = 0; + return -1; + } + } + + /* 设置调试的日志级别 */ + IOT_SetLogLevel(IOT_LOG_INFO); + +#ifdef SMARTLIVING + aiot_kv_init(); +#endif + + /* 注册链接状态的回调 */ + IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler); + IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler); + + /* 注册消息通知 */ + IOT_RegisterCallback(ITE_LINK_VISUAL, user_link_visual_handler);//linkvisual自定义消息 + IOT_RegisterCallback(ITE_SERVICE_REQUST, user_service_request_handler);//物模型服务类消息 + IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_handler);//物模型属性设置 + IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_handler);//NTP时间 + IOT_RegisterCallback(ITE_FOTA, user_fota_handler);//固件OTA升级事件 + IOT_RegisterCallback(ITE_EVENT_NOTIFY, user_event_notify_event_handler); + + if (!g_master_dev_info) { + g_master_dev_info = (iotx_linkkit_dev_meta_info_t *)malloc(sizeof(iotx_linkkit_dev_meta_info_t)); + if (!g_master_dev_info) { + printf("Malloc failed \n"); + return -1; + } + memset(g_master_dev_info, 0, sizeof(iotx_linkkit_dev_meta_info_t)); + } + string_safe_copy(g_master_dev_info->product_key, main->product_key, PRODUCT_KEY_MAXLEN - 1); + string_safe_copy(g_master_dev_info->device_name, main->device_name, DEVICE_NAME_MAXLEN - 1); + string_safe_copy(g_master_dev_info->device_secret, main->device_secret, DEVICE_SECRET_MAXLEN - 1); + string_safe_copy(g_master_dev_info->product_secret, main->product_secret, PRODUCT_SECRET_MAXLEN - 1); + + /* 选择服务器地址,当前使用上海服务器 */ + int domain_type = IOTX_CLOUD_REGION_SHANGHAI; + IOT_Ioctl(IOTX_IOCTL_SET_DOMAIN, (void *)&domain_type); + /* 动态注册 */ +#ifdef LINKKIT_DYNAMIC_REGISTER + int dynamic_register = 1; +#else + int dynamic_register = 0; +#endif + IOT_Ioctl(IOTX_IOCTL_SET_DYNAMIC_REGISTER, (void *)&dynamic_register); + +#ifdef LINKKIT_INSTANCE + int bootstrap_enabled = 1; + IOT_Ioctl(IOTX_IOCTL_SET_BOOTSTRAP_ENABLED, (void *)&bootstrap_enabled); +#endif + /* 创建linkkit资源 */ + g_master_dev_id = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, g_master_dev_info); + if (g_master_dev_id < 0) { + printf("IOT_Linkkit_Open Failed\n"); + return -1; + } + /* 连接到服务器 */ + int ret = IOT_Linkkit_Connect(g_master_dev_id); + if (ret < 0) { + printf("IOT_Linkkit_Connect Failed\n"); + return -1; + } + /* 创建线程,线程用于轮训消息 */ + g_thread_not_quit = 1; + ret = HAL_ThreadCreate(&g_thread, user_dispatch_yield, NULL, NULL, NULL); + if (ret != 0) {//!= 0 而非 < 0 + printf("HAL_ThreadCreate Failed, ret = %d\n", ret); + g_running = 0; + g_thread_not_quit = 0; + IOT_Linkkit_Close(g_master_dev_id); + return -1; + } + /* 等待主设备链接成功(demo做了有限时长的等待,实际产品中,可设置为在网络可用时一直等待) */ + for(int i = 0; i < 100; i++) { + if(!g_connect) { + HAL_SleepMs(200); + } else { + break; + } + } + if (!g_connect) { + printf("linkkit connect Failed\n"); + linkkit_client_destroy(); + return -1; + } + + printf("After start linkkit\n"); + + return 0; +} + +void linkkit_client_destroy() { + printf("Before destroy linkkit\n"); + if (!g_running) { + return; + } + g_running = 0; + + /* 等待线程退出,并释放线程资源,也可用分离式线程,但需要保证线程不使用linkkit资源后,再去释放linkkit */ + while (g_thread_not_quit) { + HAL_SleepMs(20); + } + if (g_thread) { + HAL_ThreadDelete(g_thread); + g_thread = NULL; + } + + IOT_Linkkit_Close(g_master_dev_id); + g_master_dev_id = -1; + + if (g_master_dev_info) { + free(g_master_dev_info); + g_master_dev_info = NULL; + } + if (g_sub) { + free(g_sub); + g_sub = NULL; + } + if (g_sem) { + HAL_SemaphorePost(g_sem);//让线程退出 + } + while (g_sub_thread_not_quit) { + HAL_SleepMs(20); + } + if (g_sem) { + HAL_SemaphoreDestroy(g_sem); + g_sem = NULL; + } + if (g_sub_thread) { + HAL_ThreadDelete(g_sub_thread); + g_sub_thread = NULL; + } + printf("After destroy linkkit\n"); +} + +int linkkit_message_publish_cb(const lv_message_publish_param_s *param) { + iotx_mqtt_topic_info_t topic_msg; + + /* Initialize topic information */ + memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); + topic_msg.qos = param->qos; + topic_msg.retain = 0; + topic_msg.dup = 0; + topic_msg.payload = param->message; + topic_msg.payload_len = strlen(param->message); + int rc = IOT_MQTT_Publish(NULL, param->topic, &topic_msg); + if (rc < 0) { + printf("Publish msg error:%d\n", rc); + return -1; + } + + return 0; +} + + +/* 属性设置回调 */ +void linkkit_client_set_property_handler(const lv_device_auth_s *auth, const char *value) { + /** + * 当收到属性设置时,开发者需要修改设备配置、改写已存储的属性值,并上报最新属性值。demo只上报了最新属性值。 + */ + IOT_Linkkit_Report(auth->dev_id, ITM_MSG_POST_PROPERTY, (unsigned char *)value, strlen(value)); + +} diff --git a/code/application/source/sf_app/component/liveMng/src/linkvisual_client.c b/code/application/source/sf_app/component/liveMng/src/linkvisual_client.c new file mode 100755 index 000000000..e0c01b378 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/linkvisual_client.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include +#include +#include "link_visual_struct.h" +#include "link_visual_enum.h" +#include "link_visual_api.h" +#include "iot_import.h" +#include "linkkit_client.h" +#include "sdk_assistant.h" + + +#include "linkvisual_client.h" +#include "sf_type.h" +#include "sf_param_common.h" +#include "sf_message_queue.h" + +typedef struct { + int live_main_service_id; + int live_sub_service_id; + int vod_utc_service_id; + int vod_file_service_id; + int voice_intercom_service_id; +} IpcService; +int StreamServiceID = 0; + + +void sf_live_param_get(SF_PARAM_VIDEO_AUDIO_e entype,lv_video_param_s *pvparam, lv_audio_param_s *paparam) +{ + switch(entype) + { + case SF_PARAM_MAINSTREAM: + pvparam->fps = 30; + pvparam->format = LV_VIDEO_FORMAT_H265; + pvparam->duration = 30; + pvparam->key_frame_interval_ms = 0; + + paparam->channel = LV_AUDIO_CHANNEL_MONO; + paparam->format = LV_AUDIO_FORMAT_AAC; + paparam->sample_bits = LV_AUDIO_SAMPLE_BITS_16BIT; + paparam->sample_rate = LV_AUDIO_SAMPLE_RATE_8000; + break; + case SF_PARAM_SUBSTREAM: + pvparam->fps = 30; + pvparam->format = LV_VIDEO_FORMAT_H265; + pvparam->duration = 30; + pvparam->key_frame_interval_ms = 0; + + paparam->channel = LV_AUDIO_CHANNEL_MONO; + paparam->format = LV_AUDIO_FORMAT_AAC; + paparam->sample_bits = LV_AUDIO_SAMPLE_BITS_16BIT; + paparam->sample_rate = LV_AUDIO_SAMPLE_RATE_8000; + break; + case SF_PARAM_VOICE: + break; + case SF_PARAM_STORAGE_RECORD_BY_UTC_TIME: + break; + case SF_PARAM_STORAGE_RECORD_BY_FILE: + break; + default: + printf("param undefined!!!\n"); + break; + + } + printf("entype = %d\n",entype); + +} +static void query_storage_record_cb(const lv_device_auth_s *auth, const lv_query_record_param_s *param) +{ + printf("query_storage_record_cb\n"); + /*lv_query_record_response_param_s *response = (lv_query_record_response_param_s *)malloc(sizeof(lv_query_record_response_param_s)); + memset(response, 0, sizeof(lv_query_record_response_param_s)); + + lv_post_query_record((param->common.service_id, response);*/ +} + +static void trigger_picture_cb(const lv_device_auth_s *auth, const lv_trigger_picture_param_s *param) { + +} + +static int cloud_event_cb(const lv_device_auth_s *auth, const lv_cloud_event_param_s *param) { + printf("cloud_event_cb: %d \n", param->event_type); + if (param->event_type == LV_CLOUD_EVENT_DOWNLOAD_FILE) { + printf("cloud_event_cb %d %u %s %s %s\n", + param->file_download.file_type, param->file_download.file_size, param->file_download.file_name, param->file_download.url, param->file_download.md5); + } else if (param->event_type == LV_CLOUD_EVENT_UPLOAD_FILE) { + printf("cloud_event_cb %d %s %s\n", param->file_upload.file_type, param->file_upload.file_name, param->file_upload.url); + } else if (param->event_type == LV_CLOUD_EVENT_DELETE_FILE) { + printf("cloud_event_cb %s\n", param->file_delete.file_name); +#if 0 //回复示例 + lv_cloud_event_response_param_s response; + response.reason = "http request error";//自定义内容 + response.result = 0; + lv_post_cloud_event(param->service_id, &response); +#endif + } + return 0; +} + +static int feature_check_cb(void) { +#if 1 + /* demo未实现预录事件录像,未启用预建联功能 */ + return LV_FEATURE_CHECK_CLOSE; +#else + return LV_FEATURE_CHECK_LIVE_PUBLISH + LV_FEATURE_CHECK_PRE_EVENT; +#endif +} + +static int on_push_streaming_cmd_cb(const lv_device_auth_s *auth, const lv_on_push_stream_cmd_param_s *param) { + printf("on_push_streaming_cmd_cb service_id:%d, stream_cmd_type:%d cmd:%d %d\n", + param->common.service_id, param->common.stream_cmd_type, param->common.cmd_type, param->seek.timestamp_ms); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + lv_video_param_s video_param; + lv_audio_param_s audio_param; + memset(&video_param, 0, sizeof(lv_video_param_s)); + memset(&audio_param, 0, sizeof(lv_audio_param_s)); + + lv_stream_send_config_param_s config_param = {0}; + config_param.audio_param = &audio_param; + config_param.video_param = &video_param; + config_param.bitrate_kbps = 1000; + switch(param->common.cmd_type) + { + case LV_STORAGE_RECORD_START://开始播放,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_PAUSE://暂停,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_UNPAUSE:// 继续播放,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_SEEK:// 定位,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_STOP://停止,对于录像点播有效 + + break; + case LV_STORAGE_RECORD_SET_PARAM://设置点播倍速等参数信息 + + break; + case LV_LIVE_REQUEST_I_FRAME://强制编码I帧,对于直播有效 + + sf_live_param_get(SF_PARAM_SUBSTREAM,&video_param,&audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + + stMessageBuf.cmdId = CMD_VENC; + stMessageBuf.arg1 = CMD_VENC_START_SUCCESS; + sf_com_message_send_to_app(&stMessageBuf); + StreamServiceID = param->common.service_id; + break; + case LV_VOICE_DATA: + + break; + default: + break; + } + return 0; +} + +static int on_push_streaming_data_cb(const lv_device_auth_s *auth, const lv_on_push_streaming_data_param_s *param) { + printf("Receive voice data, param = %d %d %d %d, size = %u, timestamp = %u\n", + param->audio_param->format, param->audio_param->channel, param->audio_param->sample_bits, param->audio_param->sample_rate, param->len, param->timestamp); + return 0; +} + +static int start_push_streaming_cb(const lv_device_auth_s *auth, const lv_start_push_stream_param_s *param) { + printf("start_push_streaming_cb:%d %d\n", param->common.service_id, param->common.stream_cmd_type); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + + lv_video_param_s video_param; + lv_audio_param_s audio_param; + memset(&video_param, 0, sizeof(lv_video_param_s)); + memset(&audio_param, 0, sizeof(lv_audio_param_s)); + + lv_stream_send_config_param_s config_param = {0}; + config_param.audio_param = &audio_param; + config_param.video_param = &video_param; + config_param.bitrate_kbps = 1000; + + switch(param->common.stream_cmd_type) + { + case LV_STREAM_CMD_LIVE: + stMessageBuf.cmdId = CMD_VENC; + stMessageBuf.arg1 = CMD_VENC_STREAM_START; + sf_com_message_send_to_app(&stMessageBuf); + printf("stream_type =%d\n",param->live.stream_type); + if (param->live.stream_type == 0) + { + sf_live_param_get(SF_PARAM_MAINSTREAM,&video_param,&audio_param); + } + else + { + sf_live_param_get(SF_PARAM_SUBSTREAM,&video_param,&audio_param); + } + lv_stream_send_config(param->common.service_id, &config_param); + + break; + case LV_STREAM_CMD_STORAGE_RECORD_BY_UTC_TIME: + + sf_live_param_get(SF_PARAM_STORAGE_RECORD_BY_UTC_TIME,&video_param,&audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + break; + case LV_STREAM_CMD_VOICE: + + sf_live_param_get(SF_PARAM_VOICE,&video_param,&audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + break; + case LV_STREAM_CMD_STORAGE_RECORD_BY_FILE: + + + sf_live_param_get(SF_PARAM_STORAGE_RECORD_BY_FILE,&video_param,&audio_param); + lv_stream_send_config(param->common.service_id, &config_param); + break; + case LV_STREAM_CMD_PERFORMANCE: + break; + case LV_STREAM_CMD_PRE_EVENT_RECORD: + break; + case LV_STREAM_CMD_CLOUD_STORAGE: + break; + default: + printf("undefined cmd !!!!\n"); + break; + } + return 0; +} + +static int stop_push_streaming_cb(const lv_device_auth_s *auth, const lv_stop_push_stream_param_s *param) { + printf("stop_push_streaming_cb:%d %d\n", param->service_id, param->stream_cmd_type); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = CMD_VENC; + stMessageBuf.arg1 = CMD_VENC_STREAM_STOP; + sf_com_message_send_to_app(&stMessageBuf); + StreamServiceID = 0; + + + + return 0; +} + +/** + * linkvisual_demo_init负责LinkVisual相关回调的注册。 + * 1. 开发者需要注册相关认证信息和回调函数,并进行初始化 + * 2. 根据回调函数中的信息,完成音视频流的上传 + * 3. 当前文件主要用于打印回调函数的命令,并模拟IPC的行为进行了音视频的传输 + */ +static int g_init = 0; +int linkvisual_client_init(unsigned int device_type, int sub_num, lv_log_level_e log_level) { + printf("before init linkvisual\n"); + + if (g_init) { + printf("linkvisual_demo_init already init\n"); + return 0; + } + + lv_init_config_s config; + memset(&config, 0, sizeof(lv_init_config_s)); + lv_init_callback_s callback; + memset(&callback, 0, sizeof(lv_init_callback_s)); + lv_init_system_s system; + memset(&system, 0, sizeof(lv_init_system_s)); + + /* SDK的类型配置 */ + config.device_type = device_type; + config.sub_num = sub_num; + + /* SDK的日志配置 */ + config.log_level = log_level; + config.log_dest = LV_LOG_DESTINATION_STDOUT; + + /* 码流路数限制 */ + config.storage_record_source_solo_num = 1; + config.storage_record_source_num = 4;//该参数仅对NVR有效 + + /* 图片性能控制 */ + config.image_size_max = 1024 * 1024;//内存申请不超过1M + config.image_parallel = 2;//2路并发 + + /* 码流检查功能 */ + config.stream_auto_check = 1; +#if 1 /* 码流保存为文件功能,按需使用 */ + config.stream_auto_save = 0; +#else + config.stream_auto_save = 1; + char *path = "/tmp/"; + memcpy(config.stream_auto_save_path, path, strlen(path)); +#endif + + /* das默认开启 */ + config.das_close = 0; + + +#if 1 + config.dns_mode = LV_DNS_SYSTEM; +#else + /* + * DNS配置默认使用系统内置和外部设置的 + */ + config.dns_mode = LV_DNS_SYSTEM_AND_EXTERNAL; + config.dns_num = 3; + const char *dns_ip_1 = "223.5.5.5"; + const char *dns_ip_2 = "223.6.6.6"; + const char *dns_ip_3 = "8.8.8.8"; + char *dns_servers[] = {dns_ip_1, dns_ip_2, dns_ip_3}; + config.dns_servers = dns_servers; +#endif + + callback.message_publish_cb = linkkit_message_publish_cb; + + //音视频推流服务 + callback.start_push_streaming_cb = start_push_streaming_cb; + callback.stop_push_streaming_cb = stop_push_streaming_cb; + callback.on_push_streaming_cmd_cb = on_push_streaming_cmd_cb; + callback.on_push_streaming_data_cb = on_push_streaming_data_cb; + + //获取存储录像录像列表 + callback.query_storage_record_cb = query_storage_record_cb; + + callback.trigger_picture_cb = trigger_picture_cb; + + /* 云端事件通知 */ + callback.cloud_event_cb = cloud_event_cb; + + callback.feature_check_cb = feature_check_cb; + + //先准备好LinkVisual相关资源 + int ret = lv_init(&config, &callback, &system); + if (ret < 0) { + printf("lv_init failed, result = %d\n", ret); + return -1; + } + +#if 0 + //测试SDK能否正常使用PING功能 + lv_develop_test(LV_DEVELOP_TEST_PING, 3, "aliyun.com"); +#endif + + g_init = 1; + + printf("after init linkvisual\n"); + + return 0; +} + +void linkvisual_client_destroy() { + printf("before destroy linkvisual\n"); + + if (!g_init) { + printf("linkvisual_demo_destroy is not init\n"); + return; + } + + lv_destroy(); + + g_init = 0; + + printf("after destroy linkvisual\n"); +} + +int linkvisual_client_video_handler(int service_id, lv_video_format_e format, unsigned char *buffer, unsigned int buffer_size, + unsigned int present_time, int nal_type) { + //printf("video service_id:%d, format:%d, present_time:%u nal_type:%d size %u\n", service_id, format, present_time, nal_type, buffer_size); + lv_stream_send_media_param_s param = {{0}}; + param.common.type = LV_STREAM_MEDIA_VIDEO; + param.common.p = (char *)buffer; + param.common.len = buffer_size; + param.common.timestamp_ms = present_time; + param.video.format = format; + param.video.key_frame = nal_type; + return lv_stream_send_media(service_id, ¶m); +} + +/* 音频帧数据回调 */ +int linkvisual_client_audio_handler(int service_id, + lv_audio_format_e format, + unsigned char *buffer, + unsigned int buffer_size, + unsigned int present_time) { + //printf("audio service_id:%d, present_time:%u buffer_size:%u\n", service_id, present_time, buffer_size); +#ifdef DUMMY_IPC + lv_stream_send_media_param_s param = {{0}}; + param.common.type = LV_STREAM_MEDIA_AUDIO; + param.common.p = (char *)buffer; + param.common.len = buffer_size; + param.common.timestamp_ms = present_time; + param.audio.format = format; + int ret = lv_stream_send_media(service_id, ¶m); + + for (unsigned int i = 0; i < g_ipc_num; i++) {//对讲开启时,多发送一份对讲的音频 + if (sf_stream_service_ID.live_main_service_id == service_id || sf_stream_service_ID.live_sub_service_id == service_id) { + if (sf_stream_service_ID.voice_intercom_service_id > 0) { + lv_stream_send_media(sf_stream_service_ID.voice_intercom_service_id, ¶m); + } + } + } + return ret; +#endif // DUMMY_IPC + return 0; +} + +/* 报警图片数据回调 */ +void linkvisual_client_picture_handler(const lv_device_auth_s *auth, unsigned char *buffer, unsigned int buffer_size) { + static char *data = "test"; +#if 0 + lv_alarm_event_param_s param_1; + int service_id_1; + memset(¶m_1, 0, sizeof(lv_alarm_event_param_s)); + param_1.type = LV_EVENT_MOVEMENT; + param_1.media.p = (char *)buffer; + param_1.media.len = buffer_size; + param_1.addition_string.p = data; + param_1.addition_string.len = strlen(data); + lv_post_alarm_image(auth, ¶m_1, &service_id_1); + printf("lv_post_alarm_image, service id = %d\n", service_id_1); +#else + lv_intelligent_alarm_param_s param_2; + int service_id_2; + memset(¶m_2, 0, sizeof(lv_intelligent_alarm_param_s)); + param_2.type = LV_INTELLIGENT_EVENT_MOVING_CHECK; + param_2.media.p = (char *)buffer; + param_2.media.len = buffer_size; + param_2.addition_string.p = data; + param_2.addition_string.len = strlen(data); + param_2.format = LV_MEDIA_JPEG;//该字段目前无效 + lv_post_intelligent_alarm(auth, ¶m_2, &service_id_2); + printf("lv_post_intelligent_alarm, service id = %d\n", service_id_2); +#endif +} + +int linkvisual_client_vod_handler(int service_id, int vod_cmd, int param) { + //目前只定义了点播完成的回调 + lv_stream_send_cmd(service_id, LV_STORAGE_RECORD_COMPLETE); + return 0; +} + +void linkvisual_client_query_record(int service_id, const lv_query_record_response_param_s *param) { + lv_post_query_record(service_id, param); +} + +void linkvisual_client_control_test() { + /* 一个十分简易的命令行解析程序,请按照示例命令来使用 */ +/*#define CMD_LINE_MAX (128) + char str[CMD_LINE_MAX] = {0}; + gets(str); + + char *key = strtok(str, " "); + if (!key) { + return; + } + char *value = strtok(NULL, " "); + if (!value) { + return; + } + + if (!strcmp(key, "-l")) {// 日志级别设置,使用示例: -l 3 + int log_level = value[0] - '0'; + lv_control(LV_CONTROL_LOG_LEVEL, log_level); + } else if (!strcmp(key, "-c")) {// 码流自检功能,使用示例: -c 0 + int check = value[0] - '0'; + lv_control(LV_CONTROL_STREAM_AUTO_CHECK, check); + } else if (!strcmp(key, "-s")) {// 码流自动功能,使用示例: -s 0 + int save = value[0] - '0'; + const char *path = "/tmp/";// 需要打开时,使用默认的保存路径 + lv_control(LV_CONTROL_STREAM_AUTO_SAVE, save, path); + } else { + return; + }*/ +} + +int linkvisual_client_assistant_start(unsigned int device_type, const lv_device_auth_s *main, unsigned int sub_num, const lv_device_auth_s *sub) +{ + return 0; +} + +void linkvisual_client_assistant_stop() +{ + +} diff --git a/code/application/source/sf_app/component/liveMng/src/sdk_assistant.c b/code/application/source/sf_app/component/liveMng/src/sdk_assistant.c new file mode 100755 index 000000000..28899abb0 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/sdk_assistant.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "sdk_assistant.h" + +#include +#include + +lv_device_auth_s *lvDeviceAuthCopy(const lv_device_auth_s *auth, unsigned int num) { + if (!(num && auth)) { + return NULL; + } + + lv_device_auth_s *auth_new = (lv_device_auth_s *)malloc(sizeof(lv_device_auth_s) * num); + if (!auth_new) { + return NULL; + } + memset(auth_new, 0, sizeof(lv_device_auth_s) * num); + + for (unsigned int i = 0; i < num; i++) { + auth_new[i].device_name = (char *)malloc(strlen(auth[i].device_name) + 1); + auth_new[i].product_key = (char *)malloc(strlen(auth[i].product_key) + 1); + auth_new[i].device_secret = (char *)malloc(strlen(auth[i].device_secret) + 1); + if (!(auth_new[i].device_name && auth_new[i].product_key && auth_new[i].device_secret)) { + lvDeviceAuthDelete(auth_new, i+1); + return NULL; + } + + memcpy(auth_new[i].product_key, auth[i].product_key, strlen(auth[i].product_key)); + auth_new[i].product_key[strlen(auth[i].product_key)] = '\0'; + memcpy(auth_new[i].device_name, auth[i].device_name, strlen(auth[i].device_name)); + auth_new[i].device_name[strlen(auth[i].device_name)] = '\0'; + memcpy(auth_new[i].device_secret, auth[i].device_secret, strlen(auth[i].device_secret)); + auth_new[i].device_secret[strlen(auth[i].device_secret)] = '\0'; + auth_new[i].dev_id = auth[i].dev_id; + } + + return auth_new; +} + +void lvDeviceAuthDelete(lv_device_auth_s *auth, unsigned int num) { + if (!auth) { + return; + } + + for (unsigned int i = 0; i < num; i++) { + if (auth[i].product_key) { + free(auth[i].product_key); + } + if (auth[i].device_secret) { + free(auth[i].device_secret); + } + if (auth[i].device_name) { + free(auth[i].device_name); + } + } + + free(auth); +} + +static int lvDeviceAuthCompare(const lv_device_auth_s *auth_1, const lv_device_auth_s *auth_2) { + if (!(auth_1 && auth_2 && + auth_1->product_key && auth_1->device_name && + auth_2->product_key && auth_2->device_name)) { + return -1; + } + + if (!((strlen(auth_1->product_key) == strlen(auth_2->product_key) && + memcmp(auth_1->product_key, auth_2->product_key, strlen(auth_1->product_key)) == 0))) { + return -1; + } + + if (!((strlen(auth_1->device_name) == strlen(auth_2->device_name) && + memcmp(auth_1->device_name, auth_2->device_name, strlen(auth_1->device_name)) == 0))) { + return -1; + } + + if (auth_1->dev_id != auth_2->dev_id) { + return -1; + } + + return 0; +} + +unsigned int lvDeviceAuthCompares(const lv_device_auth_s *auth_1, unsigned int num, const lv_device_auth_s *auth_2) { + if (!(auth_1 && num && auth_2)) { + return -1; + } + + unsigned int res = num; + unsigned int i = 0; + for (; i < num; i ++) { + if (lvDeviceAuthCompare(auth_1, &auth_2[i]) == 0) { + res = i; + break; + } + } + + return res; +} diff --git a/code/application/source/sf_app/component/liveMng/src/sf_liveMng.c b/code/application/source/sf_app/component/liveMng/src/sf_liveMng.c new file mode 100755 index 000000000..ea6e19ef7 --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/sf_liveMng.c @@ -0,0 +1,204 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" + +#include "sf_param_common.h" + +#include "sf_liveMng.h" +#include "iot_export_linkkit.h" +#include "sdk_assistant.h" +#include "link_visual_enum.h" +#include "link_visual_struct.h" +#include "link_visual_api.h" +#include "linkvisual_client.h" +#include "linkkit_client.h" +#define DEBUG 1 +#define MAXBUF 2048 + + + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +static SF_THREAD_S PictureHandleTskParam = +{ + .IsRun = 0, + .TskId = -1, +}; + +void sf_ipc_picture_send(int dev_id,char *filename, char *buffer, unsigned int buffer_size) +{ + + lv_intelligent_alarm_param_s param_2; + int service_id_2; + + lv_device_auth_s auth; + GetAuth(dev_id, &auth); + memset(¶m_2, 0, sizeof(lv_intelligent_alarm_param_s)); + param_2.type = LV_INTELLIGENT_EVENT_MOVING_CHECK; + param_2.media.p = (char *)buffer; + param_2.media.len = buffer_size; + param_2.addition_string.p = filename; + param_2.addition_string.len = strlen(filename); + param_2.format = LV_MEDIA_JPEG;//该字段目前无效 + lv_post_intelligent_alarm(&auth, ¶m_2, &service_id_2); + printf("lv_post_intelligent_alarm, service id = %d\n", service_id_2); +} + +int sf_ipc_picture_handle(SF_ARG_ATTR_S *parg) +{ + unsigned int buffer_len = 0; + FILE *fp = fopen(parg->filepath, "r"); + if (!fp) { + printf("Open file failed: %s\n", parg->filepath); + return -1; + } + + fseek(fp, 0, SEEK_END); + unsigned int file_size = ftell(fp); + if (file_size > 64*1024) { + printf("File is too large: %s\n", parg->filepath); + fclose(fp); + return -1; + } + + char *buffer_ = (char*)malloc(file_size); + + fseek(fp, 0, SEEK_SET); + buffer_len = fread(buffer_, 1, file_size, fp); + if(buffer_len != file_size) { + printf("File read error: %s\n", parg->filepath); + fclose(fp); + return -1; + } + fclose(fp); + + sf_ipc_picture_send(parg->dev_id,parg->filename,buffer_,file_size); + + free(buffer_); + + return 0; +} + +void sf_ipc_picture_Task(void *arg) +{ + + pthread_detach(pthread_self()); + SF_ARG_ATTR_S *pstarg = (SF_ARG_ATTR_S *)arg; + + sf_ipc_picture_handle(pstarg); + + PictureHandleTskParam.IsRun = 0; +} +void sf_ipc_Picture_thread(SF_ARG_ATTR_S *parg) +{ + MLOGD("RegisterNetTskParams.IsRun:%d\n", PictureHandleTskParam.IsRun); + if(!PictureHandleTskParam.IsRun) + { + pthread_create(&PictureHandleTskParam.TskId, NULL, (void*)sf_ipc_picture_Task, parg); + PictureHandleTskParam.IsRun = 1; + } + +} +int sf_ipc_httpsNet_init(void) +{ + + int ret = 0; + //SF_PDT_PARAM_STATISTICS_S *sim_info_t2 = sf_statistics_param_get(); + char sysCmd[128] ={0}; + + ret = system("insmod /customer/GobiNet.ko "); + //sprintf(sysCmd, "/customer/quectel-CM -s %s &",sim_info_t2->ApnGPRS); + sprintf(sysCmd, "/customer/quectel-CM -s bicsapn &"); + printf("sysCmd[%s]\n",sysCmd); + ret = system(sysCmd); + + return ret; +} + +int sf_ipc_live_init() +{ + int ret = 0; + int log_level = LV_LOG_DEBUG;//默认debug日志级别 + + ret = linkvisual_client_init(0, 0, (lv_log_level_e) log_level); + if (ret < 0) { + printf("linkvisual_client_init failed\n"); + linkvisual_client_assistant_stop(); + return -1; + } + + + iotx_linkkit_dev_meta_info_t auth = {0}; + /*string_safe_copy(auth.product_key, "a15xHjUDvCS", PRODUCT_KEY_LEN); + string_safe_copy(auth.product_secret, "", PRODUCT_SECRET_LEN); + string_safe_copy(auth.device_name, "HD_TestDevice04", DEVICE_NAME_LEN); + string_safe_copy(auth.device_secret, "b5a4404f7573d017b115f0d2df87abe", DEVICE_SECRET_LEN); + */ + /*string_safe_copy(auth.product_key, "a15xHjUDvCS", PRODUCT_KEY_LEN); + string_safe_copy(auth.product_secret, "", PRODUCT_SECRET_LEN); + string_safe_copy(auth.device_name, "HD_TestDevice02", DEVICE_NAME_LEN); + string_safe_copy(auth.device_secret, "76d807bead27907414ed327c103f8d73", DEVICE_SECRET_LEN); + */ + string_safe_copy(auth.product_key, "a15xHjUDvCS", PRODUCT_KEY_LEN); + string_safe_copy(auth.product_secret, "", PRODUCT_SECRET_LEN); + string_safe_copy(auth.device_name, "HD_TestDevice03", DEVICE_NAME_LEN); + string_safe_copy(auth.device_secret, "c7fe935e02e105907449905c7e445f20", DEVICE_SECRET_LEN); + + ret = linkkit_client_start(&auth, 0, NULL); + if (ret < 0) { + printf("linkkit_client_start failed\n"); + linkvisual_client_destroy(); + linkvisual_client_assistant_stop(); + return -1; + } + + return 0; +} +void sf_ipc_live_deinit() +{ + linkkit_client_destroy(); + linkvisual_client_destroy(); + +} + +int sf_ipc_live_writeStream(char *pu8Addr,UINT32 u32Len,UINT32 TimeStamp,UINT8 key_frame) +{ + + lv_stream_send_media_param_s stmedia_param = {0}; + + stmedia_param.common.type = LV_STREAM_MEDIA_VIDEO; + stmedia_param.common.p = pu8Addr; + stmedia_param.common.len = u32Len; + stmedia_param.common.timestamp_ms = TimeStamp/1000; + stmedia_param.video.format = LV_VIDEO_FORMAT_H265; + stmedia_param.video.key_frame = (key_frame != 1)?1:0; + //printf("TimeStamp =%ld,u32Len = %ld,key_frame = %d\n",TimeStamp,u32Len,key_frame); + if(StreamServiceID > 0) + lv_stream_send_media(StreamServiceID, &stmedia_param); + return SF_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/component/liveMng/src/sf_venc_stream.c b/code/application/source/sf_app/component/liveMng/src/sf_venc_stream.c new file mode 100755 index 000000000..a236e121e --- /dev/null +++ b/code/application/source/sf_app/component/liveMng/src/sf_venc_stream.c @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "mid_VideoEncoder.h" +#include "mi_venc.h" + +#include "sf_type.h" +#include "sf_param_common.h" +#include "sf_liveMng.h" + + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define STREAM_PACK_CNT (2) + +SF_THREAD_CFG_S stvencTask = +{ + .IsRun = 0, + .IsStopFlag = 0, +}; + + +MI_S32 _VencUserPollingStream(MI_S32 s32VencFd) +{ + MI_U32 s32Ret = 0; + fd_set read_fds; + struct timeval TimeoutVal; + + TimeoutVal.tv_sec = 0; + TimeoutVal.tv_usec = 10000; + + FD_ZERO(&read_fds); + FD_SET(s32VencFd, &read_fds); + s32Ret = select(s32VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal); + if (s32Ret < 0) { + MLOGE("[%d] select failed\n", s32VencFd); + return -1; + } else if (0 == s32Ret) { + //MLOGE("fd:%d,chn: no venc data\n", s32VencFd); + return -1; + } else if (!FD_ISSET(s32VencFd, &read_fds)) { + MLOGE("not detect venc event!\n"); + return -1; + } + + FD_CLR(s32VencFd, &read_fds); + return 0; +} +void VideoUserGetFrame(MI_VENC_Pack_t *pstPack,MI_U32 u32FrameSize, MI_U64 framePts) +{ + // Customers TODO: + // Customers need to implement this function according to their own need. + // Note that the function runs as short as possible, or it maybe drops frame! + // Here SigmaStar just dump 300 frames to file for demo. + +#if 0//(CARDV_ALINK_ENABLE) + + static int frameCnt= 0; + static int fd = 0; + char fileName[32] = {0}; + + if (frameCnt == 0) + { + sprintf(fileName,"/mnt/mmc/dump_cam0.h265"); + fd = open(fileName,O_WRONLY|O_CREAT); + } + + if (-1 != fd && frameCnt < 3000) + { + + for (int i = 0; i = 3000) + { + close(fd); + printf("recod end!!!!\n"); + } + + frameCnt ++; +#else + + for (int i = 0; i < STREAM_PACK_CNT && pstPack[i].u32Len; i++) + { + //printf("frame[%#x,%d]\n",pstPack[i].pu8Addr[4],frameType); + sf_ipc_live_writeStream((char*)pstPack[i].pu8Addr,pstPack[i].u32Len,framePts,pstPack[i].stDataType.eH265EType); + //write(fd,(char*)pstPack[i].pu8Addr,pstPack[i].u32Len); + } + + +#endif +} + +MI_S32 _VideoUserGetFrame(void) +{ + + MI_S32 _s32VencChn = 0; + MI_VENC_DupChn(_s32VencChn); + MI_S32 s32VencFd; + MI_VENC_ChnStat_t stStat; + MI_VENC_Stream_t *pstStream = NULL; + MI_S32 s32Ret = 0; + MI_U32 u32FrameSize; + + s32VencFd = MI_VENC_GetFd(_s32VencChn); + + while(stvencTask.IsRun) + { + + if (_VencUserPollingStream(s32VencFd) < 0) { + continue; + } + + memset(&stStat, 0, sizeof(MI_VENC_ChnStat_t)); + s32Ret = MI_VENC_Query(_s32VencChn, &stStat); + if (MI_SUCCESS != s32Ret || stStat.u32CurPacks == 0) { + printf("VENC Query Error\n"); + usleep(10000); // sleep 10 ms + continue; + } + + pstStream = (MI_VENC_Stream_t *)malloc(sizeof(MI_VENC_Stream_t)); + if (pstStream == NULL) { + break; + } + + pstStream->u32PackCount = STREAM_PACK_CNT; + pstStream->pstPack = (MI_VENC_Pack_t *)malloc(sizeof(MI_VENC_Pack_t) * STREAM_PACK_CNT); + if (pstStream->pstPack == NULL) { + free(pstStream); + break; + } + memset(pstStream->pstPack, 0, sizeof(MI_VENC_Pack_t) * STREAM_PACK_CNT); + + s32Ret = MI_VENC_GetStream(_s32VencChn, pstStream, 0); + if (MI_SUCCESS == s32Ret) { + // stStat.u32CurPacks is from first frame in ring pool, + // but we need get current frame info here, and we maybe already get more than one frame here. + // so we need to calculate current frame packet count. + pstStream->u32PackCount = 0; + while (pstStream->pstPack[pstStream->u32PackCount++].bFrameEnd == 0) { + if (pstStream->u32PackCount == STREAM_PACK_CNT) { + printf("STREAM_PACK_CNT not enough\n"); + break; + } + } + + u32FrameSize = 0; + for (int i = 0; i < STREAM_PACK_CNT; i++) { + u32FrameSize += pstStream->pstPack[i].u32Len; + } + + // VideoUserGetFrame(MI_VENC_Pack_t *pstPack, MI_U32 u32FrameSize, MI_U64 framePts) + VideoUserGetFrame(pstStream->pstPack, u32FrameSize, pstStream->pstPack[pstStream->u32PackCount-1].u64PTS); + //MLOGI("eH265EType :%d\n",pstStream->pstPack->stDataType.eH265EType); + // free record stream after muxer finsish done. + // printf("venc stream free [%d]\n", pstStream->u32Seq); + MI_VENC_ReleaseStream(_s32VencChn, pstStream); + free(pstStream->pstPack); + free(pstStream); + + } + + } + return s32Ret; +} +void *sf_venc_stream_thread(void *arg) +{ + _VideoUserGetFrame(); + return NULL; + +} +void sf_venc_stream_start() +{ + + if(!stvencTask.IsRun) + { + pthread_create(&stvencTask.TskId, NULL, sf_venc_stream_thread, NULL); + stvencTask.IsRun = 1; + stvencTask.IsStopFlag = 0; + } + +} +void sf_venc_stream_stop() +{ + if(stvencTask.IsRun == 0) + return; + + stvencTask.IsStopFlag = 1; + stvencTask.IsRun = 0; + pthread_join(stvencTask.TskId, NULL); +} + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/component/nfcMng/Makefile b/code/application/source/sf_app/component/nfcMng/Makefile new file mode 100755 index 000000000..f1da2dd32 --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/Makefile @@ -0,0 +1,11 @@ +CUR_ROOT := $(shell pwd) +DUAL_OS_EN ?= 1 +SF_CS_DIR :=$(CUR_ROOT)/../.. +ALKAID_DIR ?=$(SF_CS_DIR)/../../../.. +PROJECT_DIR ?=$(ALKAID_DIR)/project +include $(SF_CS_DIR)/build/config.mk + +MODULE_NAME :=$(CUR_DIR_NAME) +SRC_DIR := $(CUR_ROOT)/src + +include $(SF_CS_DIR)/build/modbuild.mk \ No newline at end of file diff --git a/code/application/source/sf_app/component/nfcMng/inc/dev_info_ctrl.h b/code/application/source/sf_app/component/nfcMng/inc/dev_info_ctrl.h new file mode 100755 index 000000000..8dc448cac --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/dev_info_ctrl.h @@ -0,0 +1,43 @@ + +#ifndef __DEV_INFO_CTRL_H +#define __DEV_INFO_CTRL_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define SIZE_OF_ARRAY(X) sizeof(X)/sizeof(X[0]) + + + + +#define SYSCTL_DEVINFO_PARAM_GET(member, pData, size) do{\ + memcpy((void*)(pData), (void*)&(DevInfo_t.member), size);\ + }while(0) + +#define SYSCTL_DEVINFO_PARAM_SET(member, pData, size) do{\ + memcpy((void*)&(DevInfo_t.member), (void*)(pData), size);\ + }while(0) + + +#define SYSCTL_DEVINFO_PARAM_GET(member, pData, size) do{\ + memcpy((void*)(pData), (void*)&(DevInfo_t.member), size);\ + }while(0) + +#define SYSCTL_DEVINFO_PARAM_SET(member, pData, size) do{\ + memcpy((void*)&(DevInfo_t.member), (void*)(pData), size);\ + }while(0) + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + + + diff --git a/code/application/source/sf_app/component/nfcMng/inc/mbedtls.h b/code/application/source/sf_app/component/nfcMng/inc/mbedtls.h new file mode 100755 index 000000000..45839a71b --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/mbedtls.h @@ -0,0 +1,25941 @@ +/* + * MbedTLS Source Code Library Header + */ + + +#if 1//ME_COM_MBEDTLS +/* +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#endif +*/ + + + +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_PLATFORM_EXIT_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_PLATFORM_PRINTF_ALT + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#define MBEDTLS_CIPHER_PADDING_PKCS7 +//#define MBEDTLS_CIPHER_PADDING_PKCS5 + + +#define MBEDTLS_AES_ROM_TABLES + + + + + + + +#if 0 //modified by ljy 20220330 + + + +/********* Start of file include/mbedtls/config.h ************/ + +/** + * \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. + * \{ + */ + +/** + * \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_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \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_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_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. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_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 Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \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. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + */ +//#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 +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_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 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#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 + +/** + * \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_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \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. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * 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 + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +#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). + */ +#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/rsa_internal.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. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#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 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#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. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#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. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#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 up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#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 + * library/rsa_internal.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 up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#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 /**< 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 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_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_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'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/* \} 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 + +/* + * 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 + + + +#endif /* MBEDTLS_CONFIG_H */ + + + + +#endif //lijiayong + + +/********* Start of file include/mbedtls/check_config.h ************/ + +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.pl. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ + + +/********* Start of file include/mbedtls/platform.h ************/ + +/** + * \file platform.h + * + * \brief The Mbed TLS platform abstraction layer. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(_WIN32) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void * (*mbedtls_calloc)( size_t n, size_t size ); +extern void (*mbedtls_free)( void *ptr ); + +/** + * \brief This function allows configuring custom memory-management functions. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function allows configuring a custom \p fprintf function pointer. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function allows configuring a custom \c printf function + * pointer. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(_WIN32) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom \c snprintf function + * pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf snprintf +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function allows configuring a custom \c exit function + * pointer. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct { + char dummy; /**< Placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else + +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform initialization operations. + * + * \param ctx The Mbed TLS context. + * + * \return \c 0 on success. + * + * \note This function is intended to allow platform-specific initialization, + * and should be called before any other library functions. Its + * implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * Its use and whether it is necessary to call it is dependent on the + * platform. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \param ctx The Mbed TLS context. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * Its use and whether it is necessary to call it is dependent on the + * platform. + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ + + +/********* Start of file include/mbedtls/platform_time.h ************/ + +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ + + +/********* Start of file include/mbedtls/threading.h ************/ + +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * 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_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct +{ + pthread_mutex_t mutex; + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ + + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ + + +/********* Start of file include/mbedtls/bignum.h ************/ + +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * 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_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mbedtls_mpi value + * \param Y Second mbedtls_mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param buf Buffer to write the string to + * \param buflen Length of buf + * \param olen Length of the string written, including final NUL byte + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with buflen = 0 to obtain the + * minimum required buffer size in *olen. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read MPI from a line in an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * MBEDTLS_ERR_MPI_XXX error code + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix 16. + * + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The unsigned integer value to multiply with + * + * \note b is unsigned + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); + +/** + * \brief Division by mbedtls_mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination mbedtls_mpi_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * + * \note The bytes obtained from the PRNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, + MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ + + +/********* Start of file include/mbedtls/net.h ************/ + +/** + * \file net.h + * + * \brief Deprecated header file that includes mbedtls/net_sockets.h + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +/********* Start of file include/mbedtls/net_sockets.h ************/ + +/** + * \file net_sockets.h + * + * \brief Network communication functions + */ +/* + * 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_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return the number of bytes received, + * or a non-zero error code: + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ + + +/********* Start of file include/mbedtls/dhm.h ************/ + +/** + * \file dhm.h + * + * \brief Diffie-Hellman-Merkle key exchange. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The DHM context structure. + */ +typedef struct +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the ServerKeyExchange parameters. + * + * \param ctx The DHM context. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function sets up and writes the ServerKeyExchange + * parameters. + * + * \param ctx The DHM context. + * \param x_size The private value size in Bytes. + * \param olen The number of characters written. + * \param output The destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The destination buffer must be large enough to hold + * the reduced binary presentation of the modulus, the generator + * and the public key, each wrapped with a 2-byte length field. + * It is the responsibility of the caller to ensure that enough + * space is available. Refer to \c mbedtls_mpi_size to computing + * the byte-size of an MPI. + * + * \note This function assumes that \c ctx->P and \c ctx->G + * have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set prime modulus and generator + * + * \param ctx The DHM context. + * \param P The MPI holding DHM prime modulus. + * \param G The MPI holding DHM generator. + * + * \note This function can be used to set P, G + * in preparation for \c mbedtls_dhm_make_params. + * + * \return \c 0 if successful, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the public value G^Y of the peer. + * + * \param ctx The DHM context. + * \param input The input buffer. + * \param ilen The size of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates its own private value \c X and + * exports \c G^X. + * + * \param ctx The DHM context. + * \param x_size The private value size in Bytes. + * \param output The destination buffer. + * \param olen The length of the destination buffer. Must be at least + equal to ctx->len (the size of \c P). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The destination buffer will always be fully written + * so as to contain a big-endian presentation of G^X mod P. + * If it is larger than ctx->len, it will accordingly be + * padded with zero-bytes in the beginning. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \param ctx The DHM context. + * \param output The destination buffer. + * \param output_size The size of the destination buffer. Must be at least + * the size of ctx->len. + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code + * on failure. + * + * \note If non-NULL, \p f_rng is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our secret value \p X is re-used and omitted + * otherwise. Therefore, we recommend always passing a + * non-NULL \p f_rng argument. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function frees and clears the components of a DHM key. + * + * \param ctx The DHM context to free and clear. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to initialize. + * \param dhmin The input buffer. + * \param dhminlen The size of the buffer, including the terminating null + * Byte for PEM data. + * + * \return \c 0 on success, or a specific DHM or PEM error code + * on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup x509_module */ +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * \param path The filename to read the DHM parameters from. + * + * \return \c 0 on success, or a specific DHM or PEM error code + * on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DHM_ALT */ + +#endif /* MBEDTLS_DHM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_constant_t) ( VAL ) ) +#else +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#endif /* ! MBEDTLS_DEPRECATED_WARNING */ + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ + + +/********* Start of file include/mbedtls/error.h ************/ + +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * 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_ERROR_H +#define MBEDTLS_ERROR_H + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 4 0x0020-0x0022 0x0023-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 11 0x0042-0x0052 0x0043-0x0045 + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 + * SHA256 1 0x0037-0x0037 + * SHA512 1 0x0039-0x0039 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 9 (Started from top) + * MD 5 5 + * CIPHER 6 8 + * SSL 6 17 (Started from top) + * SSL 7 31 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ + + +/********* Start of file include/mbedtls/md.h ************/ + + /** + * \file md.h + * + * \brief The generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Enumeration of supported message digests + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, + MBEDTLS_MD_MD2, + MBEDTLS_MD_MD4, + MBEDTLS_MD_MD5, + MBEDTLS_MD_SHA1, + MBEDTLS_MD_SHA224, + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_SHA512, + MBEDTLS_MD_RIPEMD160, +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct { + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name, + * or NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type, + * or NULL if not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \returns \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, + * #MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac
  • 0: HMAC is not used. Saves some memory.
  • + *
  • non-zero: HMAC is used with this context.
+ * + * \returns \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, or + * #MBEDTLS_ERR_MD_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, or + * #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if + * parameter verification fails. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ + + +/********* Start of file include/mbedtls/md_internal.h ************/ + +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * 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_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function in bytes */ + int size; + + /** Block length of the digest function in bytes */ + int block_size; + + /** Digest initialisation function */ + int (*starts_func)( void *ctx ); + + /** Digest update function */ + int (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + int (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + int (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Clone state from a context */ + void (*clone_func)( void *dst, const void *src ); + + /** Internal use only */ + int (*process_func)( void *ctx, const unsigned char *input ); +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ + + +/********* Start of file include/mbedtls/md5.h ************/ + +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * 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_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD5_ALT */ + +#endif /* MBEDTLS_MD5_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ + + +/********* Start of file include/mbedtls/md2.h ************/ + +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * 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_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD2_ALT */ + +#endif /* MBEDTLS_MD2_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ + + +/********* Start of file include/mbedtls/md4.h ************/ + +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * 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_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD4_ALT */ + +#endif /* MBEDTLS_MD4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ + + +/********* Start of file include/mbedtls/rsa.h ************/ + +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem. + * + * For more information, see Public-Key Cryptography Standards (PKCS) + * #1 v1.5: RSA Encryption and Public-Key Cryptography Standards + * (PKCS) #1 v2.1: RSA Cryptography Specifications. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS-1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS-1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct +{ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< \p D % (P - 1) */ + mbedtls_mpi DQ; /*!< \p D % (Q - 1) */ + mbedtls_mpi QP; /*!< 1 / (Q % P) */ + + mbedtls_mpi RN; /*!< cached R^2 mod \p N */ + + mbedtls_mpi RP; /*!< cached R^2 mod \p P */ + mbedtls_mpi RQ; /*!< cached R^2 mod \p Q */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx The RSA context to initialize. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of #mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overriden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overriden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overriden. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param P The first prime factor of \p N, or NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param D The private exponent, or NULL. + * \param E The public exponent, or NULL. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \return \c 0 on success, or a non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param N_len The Byte length of \p N, ignored if \p N == NULL. + * \param P The first prime factor of \p N, or NULL. + * \param P_len The Byte length of \p P, ignored if \p P == NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. + * \param D The private exponent, or NULL. + * \param D_len The Byte length of \p D, ignored if \p D == NULL. + * \param E The public exponent, or NULL. + * \param E_len The Byte length of \p E, ignored if \p E == NULL. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \return \c 0 on success, or a non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success, or #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the + * attempted derivations failed. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus, or NULL. + * \param P The MPI to hold the first prime factor of \p N, or NULL. + * \param Q The MPI to hold the second prime factor of \p N, or NULL. + * \param D The MPI to hold the private exponent, or NULL. + * \param E The MPI to hold the public exponent, or NULL. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies, + * or a non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, or NULL. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, or + * NULL. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, or + NULL. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, or NULL. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, or NULL. + * \param E_len The size of the buffer for the public exponent. + * + * \note The length fields are ignored if the corresponding + * buffer pointers are NULL. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies, + * or a non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold D modulo P-1, or NULL. + * \param DQ The MPI to hold D modulo Q-1, or NULL. + * \param QP The MPI to hold modular inverse of Q modulo P, or NULL. + * + * \return \c 0 on success, non-zero error code otherwise. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The RSA context to be set. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \param ctx The RSA context used to hold the key. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent. For example, 65537. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code on + * failure. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The RSA context holding the public key. + * \param prv The RSA context holding the private key. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The RSA context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for blinding. + * \param p_rng The RNG parameter. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 + * encoding, and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The input and output buffers must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 + * encoding and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer used to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the signing operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG parameter. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful, + * or an \c MBEDTLS_ERR_RSA_XXX error code + * on failure. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. + * \param src The source context. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA Context to free. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RSA_ALT */ + +#endif /* MBEDTLS_RSA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ + + +/********* Start of file include/mbedtls/rsa_internal.h ************/ + +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * + * This file declares some RSA-related helper functions useful when + * implementing the RSA interface. They are public and provided in a + * separate compilation unit in order to make it easy for designers of + * alternative RSA implementations to use them in their code, as it is + * conceived that the functionality they provide will be necessary + * for most complete implementations. + * + * End-users of Mbed TLS not intending to re-implement the RSA functionality + * are not expected to get into the need of making use of these functions directly, + * but instead should be able to use the functions declared in rsa.h. + * + * There are two classes of helper functions: + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters + * and generates some other, or CRT related parameters. + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters + * and check their validity. + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); +#ifdef __cplusplus +} +#endif + + +#endif /* rsa_internal.h */ + + +/********* Start of file include/mbedtls/asn1.h ************/ + +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * 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_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \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 MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 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 MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ + + +/********* Start of file include/mbedtls/ecp.h ************/ + +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + */ +/* + * 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_ECP_H +#define MBEDTLS_ECP_H + + + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< ECP hardware accelerator failed. */ + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain parameters (curve, subgroup and generator) identifiers. + * + * Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, + MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ + MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} mbedtls_ecp_group_id; + +/** + * Number of supported curves (plus one for NONE). + * + * (Montgomery curves excluded for now.) + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/** + * Curve information for use by other modules + */ +typedef struct +{ + mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ + uint16_t tls_id; /*!< TLS NamedCurve identifier */ + uint16_t bit_size; /*!< Curve size in bits */ + const char *name; /*!< Human-friendly name */ +} mbedtls_ecp_curve_info; + +/** + * \brief ECP point structure (jacobian coordinates) + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or Z == 1. (Other + * values of Z are used by internal functions only.) + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, X and Y are its standard (affine) coordinates. + */ +typedef struct +{ + mbedtls_mpi X; /*!< the point's X coordinate */ + mbedtls_mpi Y; /*!< the point's Y coordinate */ + mbedtls_mpi Z; /*!< the point's Z coordinate */ +} +mbedtls_ecp_point; + +/** + * \brief ECP group structure + * + * We consider two types of curves equations: + * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) + * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) + * In both cases, a generator G for a prime-order subgroup is fixed. In the + * short weierstrass, this subgroup is actually the whole curve, and its + * cardinal is denoted by N. + * + * In the case of Short Weierstrass curves, our code requires that N is an odd + * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) + * + * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is + * the quantity actually used in the formulas. Also, nbits is not the size of N + * but the required size for private keys. + * + * If modp is NULL, reduction modulo P is done using a generic algorithm. + * Otherwise, it must point to a function that takes an mbedtls_mpi in the range + * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more + * than pbits, so that the integer may be efficiently brought in the 0..P-1 + * range by a few additions or substractions. It must return 0 on success and + * non-zero on failure. + */ +typedef struct +{ + mbedtls_ecp_group_id id; /*!< internal group identifier */ + mbedtls_mpi P; /*!< prime modulus of the base field */ + mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ + mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ + mbedtls_ecp_point G; /*!< generator of the (sub)group used */ + mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ + unsigned int h; /*!< internal: 1 if the constants are static */ + int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ + void *t_data; /*!< unused */ + mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ + size_t T_size; /*!< number for pre-computed points */ +} +mbedtls_ecp_group; + +/** + * \brief ECP key pair structure + * + * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * + * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * Maximum size of the groups (that is, of N and P) + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ + +/** + * \brief Get the list of supported curves in order of preferrence + * (full information) + * + * \return A statically allocated array, the last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief Get the list of supported curves in order of preferrence + * (grp_id only) + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief Get curve information from an internal group identifier + * + * \param grp_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief Get curve information from a TLS NamedCurve value + * + * \param tls_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief Get curve information from a human-readable name + * + * \param name The name + * + * \return The associated curve information or NULL + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief Initialize a point (as zero) + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief Initialize a group (to something meaningless) + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief Initialize a key pair (as an invalid one) + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief Free the components of a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief Free the components of an ECP group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief Free the components of a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +/** + * \brief Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief Copy the contents of a group object + * + * \param dst Destination group + * \param src Source group + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); + +/** + * \brief Set a point to zero + * + * \param pt Destination point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief Tell if a point is zero + * + * \param pt Point to test + * + * \return 1 if point is zero, 0 otherwise + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief Compare two points + * + * \note This assumes the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P First point to compare + * \param Q Second point to compare + * + * \return 0 if the points are equal, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief Import a non-zero point from two ASCII strings + * + * \param P Destination point + * \param radix Input numeric base + * \param x First affine coordinate as a null-terminated string + * \param y Second affine coordinate as a null-terminated string + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief Export a point into unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to export + * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro + * \param olen Length of the actual output + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + * \note This function does NOT check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() for + * that. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief Import a point from a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Destination point + * \param buf $(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after the ECPoint on exit + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief Export a point as a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Point to export + * \param format Export format + * \param olen length of data written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Set a group using well-known domain parameters + * + * \param grp Destination group + * \param id Index in the list of well-known domain parameters + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * + * \note Index should be a value of RFC 4492's enum NamedCurve, + * usually in the form of a MBEDTLS_ECP_DP_XXX macro. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief Set a group from a TLS ECParameters record + * + * \param grp Destination group + * \param buf &(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after ECParameters on exit + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); + +/** + * \brief Write the TLS ECParameters record for a group + * + * \param grp ECP group used + * \param olen Number of bytes actually written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Multiplication by an integer: R = m * P + * (Not thread-safe to use same group in multiple threads) + * + * \note In order to prevent timing attacks, this function + * executes the exact same sequence of (base field) + * operations for any valid m. It avoids any if-branch or + * array index depending on the value of m. + * + * \note If f_rng is not NULL, it is used to randomize intermediate + * results in order to prevent potential timing attacks + * targeting these results. It is recommended to always + * provide a non-NULL f_rng (the overhead is negligible). + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey + * or P is not a valid pubkey, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Multiplication and addition of two points by integers: + * R = m * P + n * Q + * (Not thread-safe to use same group in multiple threads) + * + * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee + * a constant execution flow and timing. + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply P + * \param P Point to multiply by m + * \param n Integer by which to multiply Q + * \param Q Point to be multiplied by n + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey + * or P or Q is not a valid pubkey, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); + +/** + * \brief Check that an mbedtls_mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); + +/** + * \brief Generate a keypair with configurable base point + * + * \param grp ECP group + * \param G Chosen base point + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * in order to ease use with other structures such as + * mbedtls_ecdh_context of mbedtls_ecdsa_context. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp_id ECP group identifier + * \param key Destination keypair + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check a public-private key pair + * + * \param pub Keypair structure holding a public key + * \param prv Keypair structure holding a private (plus public) key + * + * \return 0 if successful (keys are valid and match), or + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or + * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_ALT */ + +#endif /* ecp.h */ + + +/********* Start of file include/mbedtls/ecdsa.h ************/ + +/** + * \file ecdsa.h + * + * \brief The Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * ECDSA is defined in Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_ECDSA_H +#define MBEDTLS_ECDSA_H + + + + +/* + * RFC-4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if MBEDTLS_ECP_MAX_BYTES > 124 +#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" +#endif +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) + +/** + * \brief The ECDSA context structure. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version is usually preferred. + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param md_alg The MD algorithm used to hash the message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \param grp The ECP group. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param Q The public key to use for verification. + * \param r The first integer of the signature. + * \param s The second integer of the signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + * + * \see ecp.h + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \param ctx The ECDSA context. + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes it to a buffer, + * serialized as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) and + * Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 + * + * \param ctx The ECDSA context. + * \param hash The Message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param md_alg The MD algorithm used to hash the message. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if a + * 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \return \c 0 on success, + * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The size of the hash. + * \param sig The signature to read and verify. + * \param slen The size of \p sig. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than \p siglen, + * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + * + * \see ecp.h + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \param ctx The ECDSA context to store the keypair in. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on + * failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets an ECDSA context from an EC key pair. + * + * \param ctx The ECDSA context to set. + * \param key The EC key to use. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on + * failure. + * + * \see ecp.h + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ + + +/********* Start of file include/mbedtls/ecjpake.h ************/ + +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * 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_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ + + + + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +/** + * \brief Initialize a context + * (just makes it ready for setup() or free()). + * + * \param ctx context to initialize + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up a context for use + * + * \note Currently the only values for hash/curve allowed by the + * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx context to set up + * \param role Our role: client or server + * \param hash hash function to use (MBEDTLS_MD_XXX) + * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX) + * \param secret pre-shared secret (passphrase) + * \param len length of the shared secret + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Check if a context is ready for use + * + * \param ctx Context to check + * + * \return 0 if the context is ready for use, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes) + * + * \param ctx Context to use + * \param buf Pointer to extension contents + * \param len Extension length + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange) + * + * \param ctx Context to use + * \param buf Pointer to the message + * \param len Message length + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret) + * + * \param ctx Context to use + * \param buf Buffer to write the contents to + * \param len Buffer size + * \param olen Will be updated with the number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successfull, + * a negative error code otherwise + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Free a context's content + * + * \param ctx context to free + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECJPAKE_ALT */ + +#endif /* MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* ecjpake.h */ + + +/********* Start of file include/mbedtls/pk.h ************/ + +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * 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_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#if defined(MBEDTLS_RSA_C) + +#endif + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a mbedtls_pk_context (as NONE) + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \return 0 if context can't do the operations, + * 1 otherwise. + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use - must hold a private key + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use - must hold a private key + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or MBEDTLS_PK_NONE + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ + + +/********* Start of file include/mbedtls/pk_internal.h ************/ + +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * 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_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ + + +/********* Start of file include/mbedtls/x509.h ************/ + +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * 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_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +#if defined(MBEDTLS_RSA_C) + +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) + +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ + + +/********* Start of file include/mbedtls/x509_crl.h ************/ + +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * 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_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ + + +/********* Start of file include/mbedtls/x509_crt.h ************/ + +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * 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_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs (see note above) + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 (and flags set to 0) if the chain was verified and valid, + * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified + * but found to be invalid, in which case *flags will have one + * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX + * flags set, or another error (and flags set to 0xffffffff) + * in case of a fatal error encountered during the + * verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ + + +/********* Start of file include/mbedtls/x509_csr.h ************/ + +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * 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_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *key; + mbedtls_asn1_named_data *subject; + mbedtls_md_type_t md_alg; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ + + +/********* Start of file include/mbedtls/cipher.h ************/ + +/** + * \file cipher.h + * + * \brief The generic cipher wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief An enumeration of supported ciphers. + * + * \warning ARC4 and DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, + MBEDTLS_CIPHER_ID_NULL, + MBEDTLS_CIPHER_ID_AES, + MBEDTLS_CIPHER_ID_DES, + MBEDTLS_CIPHER_ID_3DES, + MBEDTLS_CIPHER_ID_CAMELLIA, + MBEDTLS_CIPHER_ID_BLOWFISH, + MBEDTLS_CIPHER_ID_ARC4, +} mbedtls_cipher_id_t; + +/** + * \brief An enumeration of supported (cipher, mode) pairs. + * + * \warning ARC4 and DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, + MBEDTLS_CIPHER_NULL, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_CIPHER_CAMELLIA_256_CCM, +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, + MBEDTLS_MODE_ECB, + MBEDTLS_MODE_CBC, + MBEDTLS_MODE_CFB, + MBEDTLS_MODE_OFB, /* Unused! */ + MBEDTLS_MODE_CTR, + MBEDTLS_MODE_GCM, + MBEDTLS_MODE_STREAM, + MBEDTLS_MODE_CCM, +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in Bytes. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct { + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Flags to set. For example, if the cipher supports variable IV sizes or variable key sizes. */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct { + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported by the generic + * cipher module. + * + * \return A statically-allocated array of ciphers. The last entry + * is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_name, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id, or NULL if not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes and fills the cipher-context + * structure with the appropriate values. It also clears + * the structure. + * + * \param ctx The context to initialize. May not be NULL. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, + * #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context failed. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The size of the blocks of the cipher, or zero if \p ctx + * has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The mode of operation, or #MBEDTLS_MODE_NONE if + * \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return
  • If no IV has been set: the recommended IV size. + * 0 for ciphers not using IV or nonce.
  • + *
  • If IV has already been set: the actual size.
+ */ +static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of the cipher, or #MBEDTLS_CIPHER_NONE if + * \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The name of the cipher, or NULL if \p ctx has not + * been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The key length of the cipher in bits, or + * #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or + * #MBEDTLS_DECRYPT, or #MBEDTLS_OPERATION_NONE if \p ctx + * has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. May not be NULL. Must have + * been initialized using mbedtls_cipher_info_from_type() + * or mbedtls_cipher_info_from_string(). + * \param key The key to use. + * \param key_bitlen The key length to use, in bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, or a cipher-specific + * error code. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. + * \param mode The padding mode. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Only supported with GCM. Must be called + * exactly once, after mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. + * \param ad The additional data to use. + * \param ad_len the Length of \p ad. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \param ctx The generic cipher context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher, or a cipher-specific + * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * function, except the last one before + * mbedtls_cipher_finish(). Must have \p ilen as a + * multiple of the block_size. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. + * \param output The buffer to write data to. Needs block_size available. + * \param olen The length of the data written to the \p output buffer. + * + * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, + * #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or a cipher-specific error code + * on failure for any other reason. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer to write the tag to. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success, or a specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, or + * #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or a cipher-specific error code on + * failure for any other reason. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer for the authentication tag. + * \param tag_len The desired length of the authentication tag. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * a cipher-specific error code. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief The generic autenticated decryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer holding the authentication tag. + * \param tag_len The length of the authentication tag. + * + * \returns \c 0 on success, or + * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic, + * or a cipher-specific error code on failure for any other reason. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ + + +/********* Start of file include/mbedtls/cipher_internal.h ************/ + +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * 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_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ + + +/********* Start of file include/mbedtls/ssl_ciphersuites.h ************/ + +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * 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_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int id; + const char * name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ + + +/********* Start of file include/mbedtls/ecdh.h ************/ + +/** + * \file ecdh.h + * + * \brief The Elliptic Curve Diffie-Hellman (ECDH) protocol APIs. + * + * ECDH is an anonymous key agreement protocol allowing two parties to + * establish a shared secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_ECDH_H +#define MBEDTLS_ECDH_H + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key: + *
  • Our key.
  • + *
  • The key of the peer.
+ */ +typedef enum +{ + MBEDTLS_ECDH_OURS, + MBEDTLS_ECDH_THEIRS, +} mbedtls_ecdh_side; + +/** + * \brief The ECDH context structure. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +} +mbedtls_ecdh_context; + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \param grp The ECP group. + * \param d The destination MPI (private key). + * \param Q The destination point (public key). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \param grp The ECP group. + * \param z The destination MPI (shared secret). + * \param Q The public key from another party. + * \param d Our secret exponent (private key). + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks. For more information, see mbedtls_ecp_mul(). + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates a public key and a TLS + * ServerKeyExchange payload. + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context. + * \param olen The number of characters written. + * \param buf The destination buffer. + * \param blen The length of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \note This function assumes that the ECP group (grp) of the + * \p ctx context has already been properly set, + * for example, using mbedtls_ecp_group_load(). + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes a TLS ServerKeyExhange + * payload. + * + * This is the first function used by a TLS client for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context. + * \param buf The pointer to the start of the input buffer. + * \param end The address for one Byte past the end of the buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \param ctx The ECDH context to set up. + * \param key The EC key to use. + * \param side Defines the source of the key: + *
  • 1: Our key.
  • +
  • 0: The key of the peer.
+ * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and a TLS + * ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \param ctx The ECDH context. + * \param olen The number of Bytes written. + * \param buf The destination buffer. + * \param blen The size of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes a TLS ClientKeyExchange + * payload. + * + * This is the second function used by a TLS server for ECDH(E) + * ciphersuites. + * + * \param ctx The ECDH context. + * \param buf The start of the input buffer. + * \param blen The length of the input buffer. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \param ctx The ECDH context. + * \param olen The number of Bytes written. + * \param buf The destination buffer. + * \param blen The length of the destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG parameter. + * + * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code + * on failure. + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks. For more information, see mbedtls_ecp_mul(). + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ + + +/********* Start of file include/mbedtls/sha1.h ************/ + +/** + * \file sha1.h + * + * \brief The SHA-1 cryptographic hash function. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +/** + * \brief This function initializes a SHA-1 context. + * + * \param ctx The SHA-1 context to initialize. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \param ctx The SHA-1 context to clear. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \param dst The destination context. + * \param src The context to clone. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \param ctx The context to initialize. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only) + * + * \param ctx SHA-1 context + * \param data The data block being processed. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief SHA-1 context setup + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0 + * + * \param ctx The SHA-1 context to be initialized. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0 + * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA1_ALT */ + +#endif /* MBEDTLS_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \return \c 0 if successful + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = SHA-1( input buffer ) + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-1 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ + + +/********* Start of file include/mbedtls/sha256.h ************/ + +/** + * \file sha256.h + * + * \brief The SHA-224 and SHA-256 cryptographic hash function. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use. +
  • 0: Use SHA-256.
  • +
  • 1: Use SHA-224.
*/ +} +mbedtls_sha256_context; + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to initialize. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return \c 0 on success. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224 or SHA-256 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224or SHA-256 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA256_ALT */ + +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use. + *
  • 0: Use SHA-256.
  • + *
  • 1: Use SHA-224.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ + + +/********* Start of file include/mbedtls/sha512.h ************/ + +/** + * \file sha512.h + * + * \brief The SHA-384 and SHA-512 cryptographic hash function. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ + int is384; /*!< Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
*/ +} +mbedtls_sha512_context; + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0 + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA512_ALT */ + +#endif /* MBEDTLS_SHA512_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ * + * \return \c 0 on success. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use. + *
  • 0: Use SHA-512.
  • + *
  • 1: Use SHA-384.
+ */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ + + +/********* Start of file include/mbedtls/aes.h ************/ + +/** + * \file aes.h + * + * \brief The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + */ +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0023-0x0025 */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The AES context-type definition. + */ +typedef struct +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The encryption key. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + * on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The decryption key. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the AES block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must keep the maximum use of your counter in mind. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_AES_ALT */ + +#endif /* MBEDTLS_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ + + +/********* Start of file include/mbedtls/aesni.h ************/ + +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + */ +/* + * 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_AESNI_H +#define MBEDTLS_AESNI_H + + + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES-NI features detection routine + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief AES-NI AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief GCM multiplication: c = a * b in GF(2^128) + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Compute decryption round keys from encryption round keys + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ); + +/** + * \brief Perform key expansion (for encryption) + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ + + +/********* Start of file include/mbedtls/arc4.h ************/ + +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * 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_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ARC4_ALT */ + +#endif /* MBEDTLS_ARC4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ + + +/********* Start of file include/mbedtls/base64.h ************/ + +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * 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_BASE64_H +#define MBEDTLS_BASE64_H + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ + + +/********* Start of file include/mbedtls/bn_mul.h ************/ + +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * 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) + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + + + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * gcc -O0 by default uses r7 for the frame pointer, so it complains about our + * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, + * passing that option is not easy when building with yotta. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ + + +/********* Start of file include/mbedtls/camellia.h ************/ + +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * 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_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CAMELLIA context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +/** + * \brief Initialize CAMELLIA context + * + * \param ctx CAMELLIA context to be initialized + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear CAMELLIA context + * + * \param ctx CAMELLIA context to be cleared + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief CAMELLIA key schedule (encryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA key schedule (decryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key decryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA-ECB block encryption/decryption + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief CAMELLIA-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief CAMELLIA-CFB128 buffer encryption/decryption + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief CAMELLIA-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. + * + * \param ctx CAMELLIA context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_CAMELLIA_ALT */ + +#endif /* MBEDTLS_CAMELLIA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ + + +/********* Start of file include/mbedtls/ctr_drbg.h ************/ + +/** + * \file ctr_drbg.h + * + * \brief CTR_DRBG is based on AES-256, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic + * Random Bit Generators. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them using the compiler command + * line. + * \{ + */ + +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 +/**< The amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ +#else +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +/**< Amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ +#endif +#endif + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation. */ + int reseed_interval; /*!< The reseed interval. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * \note Personalization data can be provided in addition to the more generic + * entropy source, to make this instantiation as unique as possible. + * + * \param ctx The CTR_DRBG context to seed. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + length of the buffer. + * \param p_entropy The entropy context. + * \param custom Personalization data, that is device-specific + identifiers. Can be NULL. + * \param len The length of the personalization data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function clears CTR_CRBG context data. + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. The default value is + * #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be NULL. + * \param len The length of the additional data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + * + * \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, + * only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + */ +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * \param additional Additional data to update. Can be NULL. + * \param add_len The length of the additional data. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * + * \return \c 0 on success, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success, + * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, + * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +/* Internal functions (do not call directly) */ +int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ + + +/********* Start of file include/mbedtls/des.h ************/ + +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * 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_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DES_ALT */ + +#endif /* MBEDTLS_DES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ + + +/********* Start of file include/mbedtls/entropy.h ************/ + +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) + +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR + +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#if defined(MBEDTLS_HAVEGE_C) + +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct +{ + int accumulator_started; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTSL_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ + + +/********* Start of file include/mbedtls/entropy_poll.h ************/ + +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright (C) 2006-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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ + + +/********* Start of file include/mbedtls/havege.h ************/ + +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * 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_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct +{ + int PT1, PT2, offset[2]; + int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + int WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ + + +/********* Start of file include/mbedtls/memory_buffer_alloc.h ************/ + +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * 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_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ + + +/********* Start of file include/mbedtls/padlock.h ************/ + +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + */ +/* + * 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_PADLOCK_H +#define MBEDTLS_PADLOCK_H + + + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PadLock detection routine + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief PadLock AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief PadLock AES-CBC buffer en(de)cryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ + + +/********* Start of file include/mbedtls/timing.h ************/ + +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * 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_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_TIMING_ALT */ + +#endif /* MBEDTLS_TIMING_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ + + +/********* Start of file include/mbedtls/xtea.h ************/ + +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * 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_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief XTEA context structure + */ +typedef struct +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_XTEA_ALT */ + +#endif /* MBEDTLS_XTEA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ + + +/********* Start of file include/mbedtls/ssl.h ************/ + +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * 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_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + + + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + + +#endif + +#if defined(MBEDTLS_DHM_C) + +#endif + +#if defined(MBEDTLS_ECDH_C) + +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + + +#endif + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maxium fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +/* + * This structure is used for storing current session data. + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items by size (largest first) to minimize padding overhead */ + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello veirifcation */ + int (*f_cookie_write)( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*f_cookie_check)( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *p_cookie; /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*f_ticket_write)( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *p_ticket; /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + /** Callback to export key block and master secret */ + int (*f_export_keys)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t ); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< pre-shared key */ + size_t psk_len; /*!< length of the pre-shared key */ + unsigned char *psk_identity; /*!< identity for PSK negotiation */ + size_t psk_identity_len;/*!< length of identity */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + + /* + * Numerical settings (int then char) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (bitfields) + */ + + unsigned int endpoint : 1; /*!< 0: client, 1: server */ + unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned int mfl_code : 3; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + unsigned int anti_replay : 1; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + unsigned int session_tickets : 1; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + unsigned int fallback : 1; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +}; + + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif + + mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ + mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *f_recv_timeout; + /*!< Callback for network receive with timeout */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already splitted? */ +#endif + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif + void *appData; +}; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 +#define MBEDTLS_SSL_CHANNEL_INBOUND 1 + +extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); +extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Returns the list of ciphersuites supported by the SSL/TLS module. + * + * \return a statically allocated array of ciphersuites, the last + * entry is 0. + */ +const int *mbedtls_ssl_list_ciphersuites( void ); + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c mbedtls_x509_crt_verify() + * + * \param conf SSL configuration + * \param f_vrfy verification function + * \param p_vrfy verification parameter + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_sent_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \param f_export_keys Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 + * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + */ +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case mutliple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the expected identity name + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note Currently clients can only register one pre-shared key. + * In other words, the servers' identity hint is ignored. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature but + * feedback is welcomed. + * + * \param conf SSL configuration + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + + +/** + * \brief Set the Pre Shared Key (PSK) for the current handshake + * + * \note This should only be called inside the PSK callback, + * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the + * correct PSK and return 0. + * Any other return value will result in a denied PSK identity. + * + * \note If you set a PSK callback using this function, then you + * don't need to set a PSK key and identity using + * \c mbedtls_ssl_conf_psk(). + * + * \param conf SSL configuration + * \param f_psk PSK identity function + * \param p_psk PSK identity parameter + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * + * \return 0 if successful + */ +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \param conf SSL configuration + * \param bitlen Minimum bit length of the DHM prime + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * (Default: all available hashes except MD5.) + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ); +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param conf SSL configuration + * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + */ +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will likely be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \param conf SSL configuration + * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED + */ +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or + * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + */ +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or + * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or ingoing) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Return the number of data bytes available to read + * + * \param ssl SSL context + * + * \return how many bytes are available in the read buffer + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl SSL context + * + * \return 0 if successful, + * -1 if result is not available (eg because the handshake was + * aborted too early), or + * a combination of BADCERT_xxx and BADCRL_xxx flags, see + * x509.h + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is + * enabled, which makes expansion much less predictable + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes). + * This is the value negotiated with peer if any, + * or the locally configured value. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * \warning Currently, peer certificate is lost in the operation. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or + * a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after execution of this function. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * a specific SSL error code. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return the number of bytes read, or + * 0 for EOF, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or + * another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has beeen reset internally). Either way, you + * should make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return the number of bytes actually written (may be less than len), + * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, + * or another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a positive value. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_max_frag_len() may be used to query the + * active maximum fragment length. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevent fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ + + +/********* Start of file include/mbedtls/ssl_cookie.h ************/ + +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * 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_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct +{ + mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long serial; /*!< serial number for expiration */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ + + +/********* Start of file include/mbedtls/ssl_internal.h ************/ + +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * 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_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + + + + +#if defined(MBEDTLS_MD5_C) + +#endif + +#if defined(MBEDTLS_SHA1_C) + +#endif + +#if defined(MBEDTLS_SHA256_C) + +#endif + +#if defined(MBEDTLS_SHA512_C) + +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) +#define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else +#define MBEDTLS_SSL_COMPRESSION_ADD 0 +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ + + MBEDTLS_SSL_COMPRESSION_ADD \ + + MBEDTLS_MAX_IV_LENGTH \ + + MBEDTLS_SSL_MAC_ADD \ + + MBEDTLS_SSL_PADDING_ADD \ + ) + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error Bad configuration - record content too large. +#endif + +#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048 +#error Bad configuration - protected record payload too large. +#endif + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#define MBEDTLS_SSL_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) ) + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + int sni_authmode; /*!< authmode from SNI callback */ + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + unsigned char *hs_msg; /*!< Reassembled handshake message */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + unsigned char retransmit_state; /*!< Retransmission state */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context fin_sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context fin_sha512; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif +}; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length (bytes) */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); + +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl SSL context to use + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); +#endif + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 13 ); +#else + ((void) ssl); +#endif + return( 5 ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +/* constant-time buffer comparison */ +static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_internal.h */ + + +/********* Start of file include/mbedtls/ssl_cache.h ************/ + +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * 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_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t timestamp; /*!< entry timestamp */ +#endif + mbedtls_ssl_session session; /*!< entry session */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ +#endif + mbedtls_ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ + + +/********* Start of file include/mbedtls/ssl_ticket.h ************/ + +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * 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_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct +{ + unsigned char name[4]; /*!< random key identifier */ + uint32_t generation_time; /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct +{ + mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ + unsigned char active; /*!< index of the currently active key */ + + uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonnable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedlts_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedlts_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ + + +/********* Start of file include/mbedtls/debug.h ************/ + +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * 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_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + +#if defined(MBEDTLS_ECP_C) + +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ + + + +/********* Start of file include/mbedtls/blowfish.h ************/ + +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * 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_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Blowfish context structure + */ +typedef struct +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +/** + * \brief Initialize Blowfish context + * + * \param ctx Blowfish context to be initialized + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear Blowfish context + * + * \param ctx Blowfish context to be cleared + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Blowfish key schedule + * + * \param ctx Blowfish context to be initialized + * \param key encryption key + * \param keybits must be between 32 and 448 bits + * + * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Blowfish-ECB block encryption/decryption + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Blowfish-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (8 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Blowfish CFB buffer encryption/decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Blowfish-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * \param ctx Blowfish context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 64-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* blowfish.h */ + + +/********* Start of file include/mbedtls/ccm.h ************/ + +/** + * \file ccm.h + * + * \brief CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CCM_H +#define MBEDTLS_CCM_H + + + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success, or a cipher-specific error code. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \param ctx The CCM context to use for encryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \return \c 0 on success. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector. + * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag in Bytes. + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return 0 if successful and authenticated, or + * #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_CCM_ALT */ + +#endif /* MBEDTLS_CCM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ + + +/********* Start of file include/mbedtls/gcm.h ************/ + +/** + * \file gcm.h + * + * \brief Galois/Counter Mode (GCM) for 128-bit block ciphers, as defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_GCM_H +#define MBEDTLS_GCM_H + + + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#if !defined(MBEDTLS_GCM_ALT) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The GCM context structure. + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success, or a cipher specific error code. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the input buffer. + * For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context to use for encryption or decryption. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return 0 if successful and authenticated, or + * #MBEDTLS_ERR_GCM_AUTH_FAILED if tag does not match. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or NULL if \p add_len is 0. + * \param add_len The length of the additional data. If 0, \p add is NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as input buffer. + * If the buffers overlap, the output buffer must trail at least 8 Bytes + * behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. + * \param tag The buffer for holding the tag. + * \param tag_len The length of the tag to generate. Must be at least four. + * + * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#else /* !MBEDTLS_GCM_ALT */ + +#endif /* !MBEDTLS_GCM_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ + + +/********* Start of file include/mbedtls/pem.h ************/ + +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * 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_PEM_H +#define MBEDTLS_PEM_H + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required + * size. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ + + +/********* Start of file include/mbedtls/asn1write.h ************/ + +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * 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_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + + + +#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ + g += ret; } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * \param oid_len length of the OID + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + +/** + * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ + + +/********* Start of file include/mbedtls/hmac_drbg.h ************/ + +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + */ +/* + * 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_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + + + +#if defined(MBEDTLS_THREADING_C) + +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct +{ + /* Working state: the key K is not stored explicitely, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization + * Makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or + * mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding + * Seed and setup entropy source for future reseeds. + * + * \param ctx HMAC_DRBG context to be seeded + * \param md_info MD algorithm to use for HMAC_DRBG + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \note The "security strength" as defined by NIST is set to: + * 128 bits if md_alg is SHA-1, + * 192 bits if md_alg is SHA-224, + * 256 bits if md_alg is SHA-256 or higher. + * Note that SHA-256 is just as efficient as SHA-224. + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * (For use with deterministic ECDSA.) + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx HMAC_DRBG context + * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each reseed + * (Default: given by the security strength, which + * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) + * + * \param ctx HMAC_DRBG context + * \param len Amount of entropy to grab, in bytes + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) + * + * \param ctx HMAC_DRBG context + * \param interval Reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief HMAC_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (can be NULL) + * \param add_len Length of additional data (can be 0) + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param out_len Length of the buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ + + +/********* Start of file include/mbedtls/pkcs12.h ************/ + +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * 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_PKCS12_H +#define MBEDTLS_PKCS12_H + + + + + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ + + +/********* Start of file include/mbedtls/pkcs11.h ************/ + +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + */ +/* + * 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_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#if defined(MBEDTLS_PKCS11_C) + + + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context for PKCS #11 private keys. + */ +typedef struct { + pkcs11h_certificate_t pkcs11h_cert; + int len; +} mbedtls_pkcs11_context; + +/** + * Initialize a mbedtls_pkcs11_context. + * (Just making memory references valid.) + */ +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the + * mbedtls_pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \param priv_key Private key structure to cleanup + */ +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + */ +static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +{ + return ( (mbedtls_pkcs11_context *) ctx )->len; +} + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PKCS11_C */ + +#endif /* MBEDTLS_PKCS11_H */ + + +/********* Start of file include/mbedtls/pkcs5.h ************/ + +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * 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_PKCS5_H +#define MBEDTLS_PKCS5_H + + + + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ + + +/********* Start of file include/mbedtls/oid.h ************/ + +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * 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_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + + + + +#include + +#if defined(MBEDTLS_CIPHER_C) + +#endif + +#if defined(MBEDTLS_MD_C) + +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ + +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct { + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ + + +/********* Start of file include/mbedtls/ripemd160.h ************/ + +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * 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_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +#include +#include + +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_RIPEMD160_ALT */ + +#endif /* MBEDTLS_RIPEMD160_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ + + +/********* Start of file include/mbedtls/version.h ************/ + +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * 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 defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) + +#else + +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 8 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02080000 +#define MBEDTLS_VERSION_STRING "2.8.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.8.0" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ + +#endif /* ME_COM_MBEDTLS */ diff --git a/code/application/source/sf_app/component/nfcMng/inc/sf_aes.h b/code/application/source/sf_app/component/nfcMng/inc/sf_aes.h new file mode 100755 index 000000000..8b2125c8a --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/sf_aes.h @@ -0,0 +1,34 @@ +#ifndef __SF_AES_H +#define __SF_AES_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_type.h" + + +//UINT32 sf_cipher(UINT32 aesType,UINT8 operation,UINT8 *input,UINT8 *output); +UINT32 sf_cipher(UINT32 aesType,UINT8 operation,UINT8 *input,UINT8 *output, UINT8 srcl); + + + +extern void sf_cipher_test(void); +extern void sf_cipher_test1(void); + + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + + + + + + diff --git a/code/application/source/sf_app/component/nfcMng/inc/sf_dev_info.h b/code/application/source/sf_app/component/nfcMng/inc/sf_dev_info.h new file mode 100755 index 000000000..ad03f191a --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/sf_dev_info.h @@ -0,0 +1,69 @@ +#ifndef __DEV_INFO_H +#define __DEV_INFO_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#include "sf_nfc_dev.h" + + +#define IMEISTR "imei" +#define ICCID "iccid" +#define TIMESTAMP "timeStamp" +#define ACCESSKEY "accessKey" +#define CAMEDITION "camEdition" +#define SOFTWAREVERSION "softwareVersion" + + + + +struct DevInfo_t +{ + char imei[32]; + char iccid[25]; + char accessKey[20]; + char camEdition[20]; + char softwareVersion[20]; + char timeStamp[15]; +}; + + +void nfc_chip_select(void); +void nfc_chip_deselect(void); +unsigned int dev_info_deconstruct(struct DevInfo_t *pDevInfo, unsigned char *buffer, unsigned int len); +unsigned int dev_info_construct(struct DevInfo_t *pDevInfo, unsigned char *buffer, unsigned int *len); +unsigned int devinfo_write(unsigned int wAddr, unsigned char *wbuf, unsigned int wlen); +unsigned int devinfo_read(unsigned int rAddr, unsigned char *rbuf, unsigned int rlen); +unsigned int devinfo_getlen(void); + +char * devinfo_encrypt(char * buf); +char * devinfo_decrypt(char * buf); + + + +unsigned int devinfo_aes_encrypt(char * src, char * dst, unsigned int srclen); +unsigned int devinfo_aes_decrypt(char * src, char * dst, unsigned int srclen); + +unsigned int ndef_text_pack(unsigned char * src, unsigned char * dst, unsigned int srclen); +unsigned int ndef_text_depack(unsigned char * src, unsigned char * dst, unsigned int srclen); + + +void devinfo_test(void); + +void devinfo_sync(struct DevInfo_t * info); +void devinfo_store_to_rtos(unsigned char * res, unsigned int * reslen); +void devinfo_store(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + + + diff --git a/code/application/source/sf_app/component/nfcMng/inc/sf_nfc_dev.h b/code/application/source/sf_app/component/nfcMng/inc/sf_nfc_dev.h new file mode 100755 index 000000000..ae8254940 --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/sf_nfc_dev.h @@ -0,0 +1,67 @@ +#ifndef __NFC_DEV_H +#define __NFC_DEV_H + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + + + + +/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an + * unsigned long, except for: + * - I2C_FUNCS, takes pointer to an unsigned long + * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data + * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data + */ +#define I2C_RETRIES 0x0701 /* number of times a device address should + be polled when not acknowledging */ +#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */ + +/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses + * are NOT supported! (due to code brokenness) + */ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it + is already in use by a driver! */ +#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ + +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ + +#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */ + +#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ +#define I2C_SMBUS 0x0720 /* SMBus transfer */ + + +#define NFC_DEVICE_ADDRESS 0x57 + + + + + +extern int nfc_dev_init(void); +extern int nfc_dev_readData(unsigned int reg_addr, unsigned char *data, unsigned char len); +extern unsigned char nfc_dev_writeData(unsigned int reg_addr, unsigned char *data, unsigned char len); + +extern unsigned int nfc_read(unsigned int rAddr, unsigned char *rbuf, unsigned int rlen); +extern unsigned int nfc_write(unsigned int wAddr, unsigned char *wbuf, unsigned int wlen); + + +extern void nfc_dev_test(void); +extern void nfc_enhance_demodu(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + +#endif + + diff --git a/code/application/source/sf_app/component/nfcMng/inc/sf_nfc_setting.h b/code/application/source/sf_app/component/nfcMng/inc/sf_nfc_setting.h new file mode 100755 index 000000000..629f34015 --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/sf_nfc_setting.h @@ -0,0 +1,59 @@ + +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: ljy + * Ver: 1.0.0 2022.07.10 + * Description: creat +**************************************************************************/ + + +#ifndef __SF_NFC_SETTING_H +#define __SF_NFC_SETTING_H + +#define SF_NFC_MSG_CONTENT_UUID (char*)"uuid" +#define SF_NFC_MSG_CONTENT_IMEI (char*)"imei" +#define SF_NFC_MSG_CONTENT_APN (char*)"apn" +#define SF_NFC_MSG_CONTENT_USER (char*)"username" +#define SF_NFC_MSG_CONTENT_PASSWORD (char*)"password" +#define SF_NFC_MSG_CONTENT_NFCFLAG (char*)"nfcflag" + + + + +typedef enum +{ + SF_NFC_MSG_UUID = 0, + SF_NFC_MSG_IMEI, + SF_NFC_MSG_APN, + SF_NFC_MSG_USER, + SF_NFC_MSG_PASSWORD, + SF_NFC_MSG_NFCFLAG, + SF_NFC_MSG_INVALID, +}SF_NFC_MESSAGE_E; + + +typedef struct{ + SF_NFC_MESSAGE_E msg_type; + char * msg_content; +}SF_NFC_MESSAGE_t; + +void sf_json_test(void); + + +#endif + + + diff --git a/code/application/source/sf_app/component/nfcMng/inc/sf_qrutils.h b/code/application/source/sf_app/component/nfcMng/inc/sf_qrutils.h new file mode 100755 index 000000000..9d722c594 --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/inc/sf_qrutils.h @@ -0,0 +1,46 @@ + +#ifndef __SF_QRUTILS_H +#define __SF_QRUTILS_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +char* nfc_qrencrypt(char *content); + +char * nfc_qrdecrypt(char * content); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/application/source/sf_app/component/nfcMng/src/sf_dev_info.c b/code/application/source/sf_app/component/nfcMng/src/sf_dev_info.c new file mode 100755 index 000000000..8ecf91d0f --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/src/sf_dev_info.c @@ -0,0 +1,544 @@ + +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_hal_gpio.h" + +#include "sf_qrutils.h" +#include "mbedtls.h" +#include "sf_aes.h" +#include "sf_nfc_dev.h" +#include "sf_dev_info.h" +#include "dev_info_ctrl.h" +#include "sf_param_common.h" +#include "sf_systemMng.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +extern S32 sf_get_sifar_version(S8* version); + +static struct DevInfo_t devinfo; + + +static const char * dev_info_tbl[] = +{ + IMEISTR, + ICCID, + TIMESTAMP, + ACCESSKEY, + CAMEDITION, + SOFTWAREVERSION + +}; + + + + + +unsigned int dev_info_deconstruct(struct DevInfo_t *pDevInfo, unsigned char *buffer, unsigned int len) +{ + unsigned char *pBuf = (unsigned char *)buffer; + + char *p = NULL; + unsigned int contentLen = 0; + unsigned int i = 0; + while (i < SIZE_OF_ARRAY(dev_info_tbl)) + { + + p = strstr((char *)pBuf, (char *)dev_info_tbl[i]); + if (p != NULL) + { + + + switch (i) + { + case 0: /* parse imei */ + p = strchr(p + 1, ':'); + contentLen = *(p + 1); + p = strchr(p + 1, ':'); + memcpy(pDevInfo->imei, p + 1, contentLen); + + break; + + case 1: /* parse iccid */ + p = strchr(p + 1, ':'); + contentLen = *(p + 1); + p = strchr(p + 1, ':'); + memcpy(pDevInfo->iccid, p + 1, contentLen); + + break; + case 2: /* parse time */ + p = strchr(p + 1, ':'); + contentLen = *(p + 1); + p = strchr(p + 1, ':'); + memcpy(pDevInfo->timeStamp, p + 1, contentLen); + break; + case 3: /* parse accessKey */ + p = strchr(p + 1, ':'); + contentLen = *(p + 1); + p = strchr(p + 1, ':'); + memcpy(pDevInfo->accessKey, p + 1, contentLen); + break; + case 4: /* parse camEdition */ + p = strchr(p + 1, ':'); + contentLen = *(p + 1); + p = strchr(p + 1, ':'); + memcpy(pDevInfo->camEdition, p + 1, contentLen); + break; + + + case 5: /* parse softwareVersion */ + p = strchr(p + 1, ':'); + contentLen = *(p + 1); + p = strchr(p + 1, ':'); + memcpy(pDevInfo->softwareVersion, p + 1, contentLen); + break; + + default: + printf("there is nothing to parse!!!\r\n"); + break; + } + } + + + i++; + } + + + + return 0; + +} + + + + + + + +unsigned int dev_info_construct(struct DevInfo_t *pDevInfo, unsigned char *buffer, unsigned int *len) +{ + +#define START_FLAG 0x7B +#define END_FLAG 0x7D +#define COLON 0x3A +#define COMMA 0x2c + unsigned int index = 0; + unsigned int totallen = 0; + + buffer[index] = START_FLAG; + index++; + + buffer[index] = totallen; + index++; + + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], IMEISTR, strlen(IMEISTR)); + index += strlen(IMEISTR); + buffer[index] = COLON; + index++; + + buffer[index] = strlen(pDevInfo->imei); + index++; + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], pDevInfo->imei, strlen(pDevInfo->imei)); + index += strlen(pDevInfo->imei); + + buffer[index] = COMMA; + index++; + + memcpy(&buffer[index], ICCID, strlen(ICCID)); + index += strlen(ICCID); + buffer[index] = COLON; + index++; + + buffer[index] = strlen(pDevInfo->iccid); + index++; + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], pDevInfo->iccid, strlen(pDevInfo->iccid)); + index += strlen(pDevInfo->iccid); + + buffer[index] = COMMA; + index++; + + memcpy(&buffer[index], ACCESSKEY, strlen(ACCESSKEY)); + index += strlen(ACCESSKEY); + buffer[index] = COLON; + index++; + + buffer[index] = strlen(pDevInfo->accessKey); + index++; + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], pDevInfo->accessKey, strlen(pDevInfo->accessKey)); + index += strlen(pDevInfo->accessKey); + + + buffer[index] = COMMA; + index++; + + memcpy(&buffer[index], SOFTWAREVERSION, strlen(SOFTWAREVERSION)); + index += strlen(SOFTWAREVERSION); + buffer[index] = COLON; + index++; + + buffer[index] = strlen(pDevInfo->softwareVersion); + index++; + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], pDevInfo->softwareVersion, strlen(pDevInfo->softwareVersion)); + index += strlen(pDevInfo->softwareVersion); + + + buffer[index] = COMMA; + index++; + + memcpy(&buffer[index], CAMEDITION, strlen(CAMEDITION)); + index += strlen(CAMEDITION); + buffer[index] = COLON; + index++; + + buffer[index] = strlen(pDevInfo->camEdition); + index++; + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], pDevInfo->camEdition, strlen(pDevInfo->camEdition)); + index += strlen(pDevInfo->camEdition); + + buffer[index] = COMMA; + index++; + + memcpy(&buffer[index], TIMESTAMP, strlen(TIMESTAMP)); + index += strlen(TIMESTAMP); + buffer[index] = COLON; + index++; + + buffer[index] = strlen(pDevInfo->timeStamp); + index++; + buffer[index] = COLON; + index++; + + memcpy(&buffer[index], pDevInfo->timeStamp, strlen(pDevInfo->timeStamp)); + index += strlen(pDevInfo->timeStamp); + + buffer[index] = END_FLAG; + + buffer[1] = index + 1; + *len = index + 1; + return 0; +} + + + +unsigned int devinfo_write(unsigned int wAddr, unsigned char *wbuf, unsigned int wlen) +{ + + nfc_write(wAddr, wbuf, wlen); + return 0; + + +} + + +unsigned int devinfo_read(unsigned int rAddr, unsigned char *rbuf, unsigned int rlen) +{ + + nfc_read(rAddr, rbuf, rlen); + return 0; + + +} + + +unsigned int devinfo_getlen(void) +{ + unsigned int len = 0; + char tmpBuf[17] = {0}; + unsigned int rAddr = 0x0010; + nfc_dev_readData(rAddr, (unsigned char *)tmpBuf, 16); + char * p = NULL; + + p = strchr(tmpBuf, '{'); + if (p != NULL) + { + len = *(p + 1); + return len; + } + else + { + printf("parse rbuf len is 0!!!!\r\n"); + return -1; + } + +} + + + + +unsigned int devinfo_wirte_mark(unsigned int wAddr, unsigned char *wbuf, unsigned int wlen) +{ + + devinfo_write(wAddr, wbuf, wlen); + return 0; +} + + + +unsigned int devinfo_read_mark(unsigned int rAddr, unsigned char *rbuf, unsigned int rlen) +{ + devinfo_read(rAddr, rbuf, rlen); + return 0; +} + + + +char * devinfo_encrypt(char * buf) +{ + + return nfc_qrencrypt(buf); +} + +char * devinfo_decrypt(char * buf) +{ + return nfc_qrdecrypt(buf); +} + + + +unsigned int devinfo_aes_encrypt(char * src, char * dst, unsigned int srclen) +{ + return sf_cipher(MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_ENCRYPT, (UINT8 *)src, (UINT8 *)dst, (UINT8)srclen); +} + +unsigned int devinfo_aes_decrypt(char * src, char * dst, unsigned int srclen) +{ + return sf_cipher(MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_DECRYPT, (UINT8 *)src, (UINT8 *)dst, (UINT8)srclen); + +} + +unsigned int ndef_text_pack(unsigned char * src, unsigned char * dst, unsigned int srclen) +{ + dst[0] = 0x03; + dst[1] = 7 + srclen; + dst[2] = 0xd1; + dst[3] = 1; + dst[4] = srclen + 3; + dst[5] = 'T'; + dst[6] = 0x02; + dst[7] = 'e'; + dst[8] = 'n'; + memcpy(&dst[9], src, srclen); + dst[9 + srclen] = 0xfe; + return (9 + srclen + 1); +} + + +unsigned int ndef_text_depack(unsigned char * src, unsigned char * dst, unsigned int srclen) +{ + unsigned int dstlen = 0; + dstlen = srclen - 10; + memcpy(dst, &src[9], dstlen); + return dstlen; + +} + + + +void nfc_chip_select(void) +{ + + sf_hal_gpio_init(12, (char*)"out"); + sf_hal_gpio_set(12, 0); + +} + +void nfc_chip_deselect(void) +{ + sf_hal_gpio_init(12, (char*)"out"); + sf_hal_gpio_set(12, 1); +} + + + + + + +void devinfo_sync(struct DevInfo_t * info) +{ + + SF_PDT_PARAM_STATISTICS_S* pPDTParam = sf_statistics_param_get(); + + time_t timep; + struct tm* p; + char timebuf[32] = {0}; + char version[20] = {0}; + time(&timep); + p = localtime(&timep); + + sprintf((char*)timebuf, "%02d%02d%02d%02d%02d%02d", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, + (p->tm_hour), p->tm_min, p->tm_sec); + + + memset(info, 0x00, sizeof(struct DevInfo_t)); + + memcpy(info->accessKey, "ACR7CSCAWO01", strlen("ACR7CSCAWO01")); + memcpy(info->camEdition, "T1CS-SY-R-O01", strlen("T1CS-SY-R-O01")); + sf_sys_software_version_get(version); + memcpy(info->softwareVersion, version, strlen(version)); + + + memcpy(info->iccid, pPDTParam->SimID, strlen(pPDTParam->SimID)); + memcpy(info->imei, pPDTParam->IMEI, strlen(pPDTParam->IMEI)); + + memcpy(info->timeStamp, timebuf, strlen(timebuf)); + + +} + + + +void devinfo_store(void) +{ + + + unsigned char buf[256] = {0}; + unsigned int len = 0; + unsigned char dst[256] = {0}; + unsigned char rear_wbuf[512] = {0}; + + devinfo_sync(&devinfo); + dev_info_construct(&devinfo, buf, &len); + len = devinfo_aes_encrypt((char *)buf, (char *)dst, len); + + len = ndef_text_pack(dst, rear_wbuf, len); + nfc_chip_select(); + devinfo_write(0x0010, rear_wbuf, len); + nfc_chip_deselect(); +} + +void devinfo_store_to_rtos(unsigned char * res, unsigned int * reslen) +{ + + + unsigned char src[256] = {0}; + unsigned int len = 0; + unsigned char dst[256] = {0}; + + devinfo_sync(&devinfo); + dev_info_construct(&devinfo, src, &len); + + len = devinfo_aes_encrypt((char *)src, (char *)dst, len); + len = ndef_text_pack(dst, res, len); + *reslen = len; +} + + +/* +void sf_get_devinfo(struct DevInfo_t *pDevInfo, unsigned char * src, unsigned int srclen) +{ + unsigned int len = 0; + unsigned int dstlen = 0; + unsigned char dst[256] = {0}; + unsigned char dst1[256] = {0}; + + len = ndef_text_depack(src, dst, srclen); + dstlen = devinfo_aes_decrypt(dst, dst1, len); + dev_info_deconstruct(pDevInfo, dst1, dstlen); + +} +*/ + + + + + + + + + +void devinfo_test(void) +{ + + devinfo_sync(&devinfo); + + + unsigned char wbuf[256] = {0}; + unsigned char rear_wbuf[512] = {0}; + unsigned char dst[256] = {0};//depackBuf + unsigned char depackBuf[256] = {0};//depackBuf + unsigned int wlen = 0; + unsigned int enclen = 0; + unsigned int declen = 0; + dev_info_construct(&devinfo, wbuf, &wlen); + + + + + printf("wbuf is %s\r\n", wbuf); + + printf("wlen is %d\r\n", wlen); + + printf("before qr len is %d\r\n", strlen((char *)wbuf)); + + //devinfo_encrypt((char *)wbuf); + + enclen = devinfo_aes_encrypt((char *)wbuf, (char *)dst, strlen((char *)wbuf)); + + printf("after qr len is %d\r\n", strlen((char *)dst)); + + printf("after encode, dst is %s\r\n", dst); + + + wlen = ndef_text_pack(dst, rear_wbuf, enclen); + printf("ndef_text_pack is %d %d\r\n", wlen, enclen); + //unsigned int ndef_text_depack(unsigned char * src, unsigned char * dst, unsigned int srclen) + + unsigned char wbuf1[256] = {0}; + devinfo_write(0x0010, wbuf1, 256); + devinfo_write(0x0010, rear_wbuf, wlen); + + + declen = ndef_text_depack(rear_wbuf, depackBuf, wlen); + + enclen = 0; + memset(dst, 0x00, sizeof(dst)); + enclen = devinfo_aes_decrypt((char *)depackBuf, (char *)dst, declen); + + + + printf("parse rbuf!!!! %s, len %d\r\n", dst, enclen); + struct DevInfo_t devinfo1; + memset(&devinfo1, 0, sizeof(devinfo1)); + dev_info_deconstruct(&devinfo1, dst, enclen); + + + + return; + + + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/application/source/sf_app/component/nfcMng/src/sf_nfc_dev.c b/code/application/source/sf_app/component/nfcMng/src/sf_nfc_dev.c new file mode 100755 index 000000000..7778ed01e --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/src/sf_nfc_dev.c @@ -0,0 +1,317 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sf_nfc_dev.h" +#include "sf_dev_info.h" +#include "dev_info_ctrl.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +/** + * @fn nfc_dev_init + * @author lijiayong 20220314 + * @brief nfc device init-gpio config + * @param + * @retval fail--1 success-0 + */ +int nfc_dev_init(void) +{ + return 0; +} + +/** + * @fn nfc_dev_readData + * @author lijiayong 20220314 + * @brief nfc device read data from reg + * @param + * @retval fail--1 success-0 + */ +int nfc_dev_readData(unsigned int reg_addr, unsigned char* data, unsigned char len) +{ + int retval = -1; + int fd = -1; + char file_name[0x10] = {0}; + unsigned char addr[2] = {0}; + + + addr[0] = (reg_addr >> 8) & 0x00ff; + addr[1] = reg_addr & 0x00ff; + + + sprintf(file_name, "/dev/i2c-0"); + fd = open(file_name, O_RDWR); + if (fd < 0) + { + printf("Open %s error!\n",file_name); + retval = -1; + return retval; + } + + retval = ioctl(fd, I2C_TENBIT, 0); + if (retval < 0) + { + printf("I2C_TENBIT error!,retval:%d\n",retval); + retval = -1; + close(fd); + return retval; + } + retval = ioctl(fd, I2C_SLAVE_FORCE, NFC_DEVICE_ADDRESS); + if (retval < 0) + { + printf("CMD_SET_I2C_SLAVE error!,retval:%d\n",retval); + retval = -1; + close(fd); + return retval; + } + + if(write(fd, addr, 2) < 0) + { + printf("Write Error.\n"); + retval = -1; + close(fd); + return retval; + } + + if(read(fd, data, len) < 0) + { + printf("Read Error.\n"); + retval = -1; + close(fd); + return retval; + } + + retval = 0; + + close(fd); + return retval; + +} + + + + +/** + * @fn nfc_dev_writeData + * @author lijiayong 20220314 + * @brief nfc device write data into reg or eeprom + * @param + * @retval fail--1 success-0 + */ +unsigned char nfc_dev_writeData(unsigned int reg_addr, unsigned char* data, unsigned char len) +{ + int retval = -1; + int fd = -1; + int index = 0; + char file_name[0x10] = {0}; + unsigned char buf[len + 2]; + + sprintf(file_name, "/dev/i2c-0"); + fd = open(file_name, O_RDWR); + if (fd<0) + { + printf("Open %s error!\n", file_name); + retval = -1; + return retval; + } + + retval = ioctl(fd, I2C_TENBIT, 0); + if(retval < 0) + { + printf("set i2c device I2C_TENBIT error!\n"); + retval = -1; + close(fd); + return retval; + } + retval = ioctl(fd, I2C_SLAVE_FORCE, NFC_DEVICE_ADDRESS); + if(retval < 0) + { + printf("set i2c device address error!\n"); + retval = -1; + close(fd); + return retval; + } + + + buf[index] = (reg_addr >> 8) & 0x00ff; + index++; + + buf[index] = reg_addr & 0x00ff; + index++; + + for(unsigned char i = 0; i < len; i++) + { + buf[index] = *data; + data++; + index++; + } + + + retval = write(fd, buf, len + 2); + if(retval < 0) + { + printf("i2c write error!retval:%d\n",retval); + retval = -1; + close(fd); + return retval; + } + + close(fd); + retval = 0; + return retval; + +} + + + + + + + +unsigned int nfc_read(unsigned int rAddr, unsigned char *rbuf, unsigned int rlen) +{ + + unsigned int toReadLen = 0; + + while (rlen > 0) + { + if (rlen >= 16) + { + toReadLen = 16; + } + else + { + toReadLen = rlen; + } + + rlen -= toReadLen; + nfc_dev_readData(rAddr, rbuf, toReadLen); + rbuf += toReadLen; + rAddr += toReadLen; + } + + + return 0; +} + + + + +unsigned int nfc_write(unsigned int wAddr, unsigned char *wbuf, unsigned int wlen) +{ + + unsigned int toWriteLen = 0; + + while (wlen > 0) + { + if (wlen >= 16) + { + + toWriteLen = 16; + } + else + { + toWriteLen = wlen; + } + wlen -= toWriteLen; + + + nfc_dev_writeData(wAddr, wbuf, toWriteLen); + wbuf += toWriteLen; + wAddr += toWriteLen; + } + return 0; + +} + + + + + + + + +void nfc_dev_test(void) +{ + + + + unsigned char wbuf[] = "777"; + unsigned char rbuf[20] = {0}; + /*write command*/ + + nfc_dev_writeData(0x0010, wbuf, sizeof(wbuf)); + printf("nfc device write done!\r\n"); + nfc_dev_readData(0x0010, rbuf, 16); + printf("nfc device read data is %s\r\n", rbuf); + + + + nfc_dev_writeData(0x0011, wbuf, sizeof(wbuf)); + printf("nfc device write done!\r\n"); + nfc_dev_readData(0x0011, rbuf, 16); + printf("nfc device read data is %s\r\n", rbuf); + + memset(rbuf, 0, sizeof(rbuf)); + nfc_dev_readData(0xffe0, rbuf, 1); + printf("nfc device read data is 0x%x\r\n", rbuf[0]); + + + memset(rbuf, 0, sizeof(rbuf)); + nfc_dev_readData(0xffe1, rbuf, 1); + printf("nfc device read data is 0x%x\r\n", rbuf[0]); + memset(rbuf, 0, sizeof(rbuf)); + nfc_dev_readData(0xffe2, rbuf, 1); + printf("nfc device read data is 0x%x\r\n", rbuf[0]); + + memset(rbuf, 0, sizeof(rbuf)); + nfc_dev_readData(0xffe6, rbuf, 1); + printf("nfc device read data is 0x%x\r\n", rbuf[0]); + +} + + + +void nfc_enhance_demodu(void) +{ + unsigned char data[16] = {0}; + unsigned int writeAddr = 0x00; + unsigned int len = 0; + writeAddr = 0xe0 * 0x04; + data[0] = 0xb0;//10110000;// + data[1] = 0x84;//10000100;// + data[2] = 0x21;//00100001;// + data[3] = ~(data[2] ^ data[1] ^ data[0]); + len = 4; + nfc_dev_writeData(writeAddr, data, len); + + memset(data, 0x00, 16); + + nfc_dev_readData(writeAddr, data, 4); + printf("cfg0 0x%x, cfg1 0x%x, cfg2 0x%x, crc 0x%x\r\n", data[0], data[1], data[2], data[3]); + + + +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + + diff --git a/code/application/source/sf_app/component/nfcMng/src/sf_nfc_setting.c b/code/application/source/sf_app/component/nfcMng/src/sf_nfc_setting.c new file mode 100755 index 000000000..819db9dfb --- /dev/null +++ b/code/application/source/sf_app/component/nfcMng/src/sf_nfc_setting.c @@ -0,0 +1,202 @@ +/************************************************************************** + * + * Copyright (c) 2015-2020 by WuYuan Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * WuYuan Technology, Inc. reserves the right to modify this software without notice. + * + * Author: ljy + * Ver: 1.0.0 2022.07.10 + * Description: creat +**************************************************************************/ +#include +#include +#include +#include +#include + +#include "sf_nfc_setting.h" +#include "cJSON.h" +#include "sf_nfc_dev.h" +#include "sf_dev_info.h" + + +char json_sample[] = "{\ +\"imei\":\"867648049049388\",\ +\"uuid\":\"123\",\ +\"apn\":\"cmnet\",\ +\"username\":\"ljy\",\ +\"password\":\"123456\",\ +\"nfcflag\":1\ +}"; + + + + +SF_NFC_MESSAGE_t sf_nfc_msg[SF_NFC_MSG_INVALID] = +{ + {SF_NFC_MSG_UUID, SF_NFC_MSG_CONTENT_UUID}, + {SF_NFC_MSG_IMEI, SF_NFC_MSG_CONTENT_IMEI}, + {SF_NFC_MSG_APN, SF_NFC_MSG_CONTENT_APN}, + {SF_NFC_MSG_USER, SF_NFC_MSG_CONTENT_USER}, + {SF_NFC_MSG_PASSWORD, SF_NFC_MSG_CONTENT_PASSWORD}, + {SF_NFC_MSG_NFCFLAG, SF_NFC_MSG_CONTENT_NFCFLAG}, +}; + + + + + +SINT32 sf_nfc_check_flag(void) +{ + + return 0; + +} + +void sf_nfc_msg_erase_all(void) +{ + unsigned char wbuf[256] = {0}; + memset(wbuf, 0xff, 256); + nfc_write(0x0210, wbuf, 256); +} + +SINT32 sf_nfc_read_json_resource(char* json) +{ + char rbuf[256] = {0}; + char payload_buf[256] = {0}; + UINT32 rlen = 0; + UINT32 payload_len = 0; + rlen = nfc_read(0x0210, (unsigned char*)rbuf, 256); + payload_len = ndef_text_depack((unsigned char*)rbuf, (unsigned char*)payload_buf, rlen); + devinfo_aes_decrypt(payload_buf, json, payload_len); + + return 0; + +} + +SINT32 sf_nfc_write_json_resource(char* json, unsigned int len) +{ + UINT32 ndef_len = 0; + UINT32 wlen = 0; + char ndef_buf[256] = {0}; + char wbuf[256] = {0}; + ndef_len = ndef_text_pack((unsigned char*)json, (unsigned char*)ndef_buf, len); + wlen = devinfo_aes_encrypt(ndef_buf, wbuf, ndef_len); + nfc_write(0x0210, (unsigned char*)wbuf, wlen); + return 0; +} + + + + +SINT32 sf_nfc_read_item(SF_NFC_MESSAGE_E id, char * src, cJSON * json_res) +{ + cJSON * json_str = cJSON_Parse(src); + if(json_str == NULL) + { + printf("[error]src is not json data!!!!\r\n"); + cJSON_Delete(json_str); + return -1; + } + + +/* + json_res = cJSON_GetObjectItem(json_str, sf_nfc_msg[id].msg_content); + if(json_res != NULL) + { + cJSON_Delete(json_str); + return 0; + } +*/ + + + switch(id) + { + case SF_NFC_MSG_UUID: + + json_res = cJSON_GetObjectItem(json_str, SF_NFC_MSG_CONTENT_UUID); + if(json_res != NULL && json_res->type == cJSON_String) + { + printf("[SF_NFC_MSG_CONTENT_UUID] = %s\n", json_res->valuestring); + //memcpy(dst, (char*)json_res->valuestring, sizeof(json_res->valuestring)); + } + break; + + case SF_NFC_MSG_IMEI: + json_res = cJSON_GetObjectItem(json_str, SF_NFC_MSG_CONTENT_IMEI); + if(json_res != NULL && json_res->type == cJSON_String) + { + printf("[SF_NFC_MSG_CONTENT_IMEI] = %s\n", json_res->valuestring); + //memcpy(dst, (char*)json_res->valuestring, sizeof(json_res->valuestring)); + } + break; + + case SF_NFC_MSG_APN: + json_res = cJSON_GetObjectItem(json_str, SF_NFC_MSG_CONTENT_APN); + if(json_res != NULL && json_res->type == cJSON_String) + { + printf("[SF_NFC_MSG_CONTENT_APN] = %s\n", json_res->valuestring); + //memcpy(dst, (char*)json_res->valuestring, sizeof(json_res->valuestring)); + } + break; + + case SF_NFC_MSG_USER: + json_res = cJSON_GetObjectItem(json_str, SF_NFC_MSG_CONTENT_USER); + if(json_res != NULL && json_res->type == cJSON_String) + { + printf("[SF_NFC_MSG_CONTENT_USER] = %s\n", json_res->valuestring); + //memcpy(dst, (char*)json_res->valuestring, sizeof(json_res->valuestring)); + } + break; + + case SF_NFC_MSG_PASSWORD: + json_res = cJSON_GetObjectItem(json_str, SF_NFC_MSG_CONTENT_PASSWORD); + if(json_res != NULL && json_res->type == cJSON_String) + { + printf("[SF_NFC_MSG_CONTENT_PASSWORD] = %s\n", json_res->valuestring); + //memcpy(dst, (char*)json_res->valuestring, sizeof(json_res->valuestring)); + } + break; + + case SF_NFC_MSG_NFCFLAG: + json_res = cJSON_GetObjectItem(json_str, SF_NFC_MSG_CONTENT_NFCFLAG); + if(json_res != NULL && json_res->type == cJSON_Number) + { + printf("[SF_NFC_MSG_CONTENT_NFCFLAG] = %d\n", json_res->valueSINT32); + //memcpy(dst, (char*)json_res->valueSINT32, sizeof(json_res->valueSINT32)); + } + break; + + default: + break; + + } + + cJSON_Delete(json_str); + return 0; +} + +void sf_json_test(void) +{ + cJSON json_res; + char json_data[256] = {0}; + + sf_nfc_write_json_resource(json_sample, strlen(json_sample)); + + sf_nfc_read_json_resource(json_data); + + + for(int i = 0; i < SF_NFC_MSG_INVALID; i++) + sf_nfc_read_item(sf_nfc_msg[i].msg_type, json_data, &json_res); + +} + diff --git a/code/application/source/sf_app/component/updataMng/Makefile b/code/application/source/sf_app/component/updataMng/Makefile new file mode 100755 index 000000000..f1da2dd32 --- /dev/null +++ b/code/application/source/sf_app/component/updataMng/Makefile @@ -0,0 +1,11 @@ +CUR_ROOT := $(shell pwd) +DUAL_OS_EN ?= 1 +SF_CS_DIR :=$(CUR_ROOT)/../.. +ALKAID_DIR ?=$(SF_CS_DIR)/../../../.. +PROJECT_DIR ?=$(ALKAID_DIR)/project +include $(SF_CS_DIR)/build/config.mk + +MODULE_NAME :=$(CUR_DIR_NAME) +SRC_DIR := $(CUR_ROOT)/src + +include $(SF_CS_DIR)/build/modbuild.mk \ No newline at end of file diff --git a/code/application/source/sf_app/component/updataMng/inc/sf_md5.h b/code/application/source/sf_app/component/updataMng/inc/sf_md5.h new file mode 100755 index 000000000..01c92cbd7 --- /dev/null +++ b/code/application/source/sf_app/component/updataMng/inc/sf_md5.h @@ -0,0 +1,35 @@ +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: HAC + * Ver: 1.0.0 2021.10.31 + * Description: creat +**************************************************************************/ +#ifndef __SF_MD5_H__ +#define __SF_MD5_H__ + +typedef struct +{ + unsigned int state[4]; + unsigned int count[2]; + unsigned char buffer[64]; +} MD5_CTX; + +void sf_md5_init(MD5_CTX *context); +void sf_md5_update(MD5_CTX *context, unsigned char *input, unsigned int inputlen); +void sf_md5_final(MD5_CTX *context, unsigned char digest[16]); + +#endif + diff --git a/code/application/source/sf_app/component/updataMng/inc/sf_otamng.h b/code/application/source/sf_app/component/updataMng/inc/sf_otamng.h new file mode 100755 index 000000000..ddc63893f --- /dev/null +++ b/code/application/source/sf_app/component/updataMng/inc/sf_otamng.h @@ -0,0 +1,67 @@ + +#ifndef _SF_OTAMNG_H_ +#define _SF_OTAMNG_H_ +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#include "sf_log.h" +#include "sf_param_common.h" + + + +#define OTAFILE_PATH "/mnt/mmc/ota.txt" +#define OTA_UPGRADE_FILE_NAME "UpgradeSD.bin" +#define OTA_CFG_FILE_NAME "T110Upgrade.CFG" +#define OTA_BAK_FILE_NAME "backup.txt" + +#define OTA_UPGRADE_FATH_PREFIX "/mnt/mmc" +#define OTA_UPGRADE_FILE_PATH OTA_UPGRADE_FATH_PREFIX "/" OTA_UPGRADE_FILE_NAME +#define OTA_CFG_FILE_PATH OTA_UPGRADE_FATH_PREFIX "/" OTA_CFG_FILE_NAME + +#define SF_OTA_UPGRADE_FILE_PATH SF_SD_ROOT OTA_UPGRADE_FILE_NAME +#define SF_OTA_PARAM_BACKUP_FATH SF_SD_ROOT OTA_BAK_FILE_NAME + +typedef struct sf_ota_attrs { + int server_type; + char server_url[128]; + char server_host[64]; + char filepath[64]; + char filename[64]; + int filesize; + char *host; + int socket; + //SSL *ssl; + //SSL_CTX *ctx; +} SF_OTA_ATTRS; +SINT32 upgrade_ota_file_IsExsit(SF_CHAR *fileName); + +SINT32 sf_upgrade_ota_init(void); + +SINT32 sf_upgrade_ota_download(void); + +SINT32 sf_upgrade_ota_env_set(void); + +SINT32 sf_upgrade_ota_reset(void); + +SINT32 sf_upgrade_ota_deinit(void); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + + +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + +#endif + + diff --git a/code/application/source/sf_app/component/updataMng/src/sf_md5.c b/code/application/source/sf_app/component/updataMng/src/sf_md5.c new file mode 100755 index 000000000..c77ac9b55 --- /dev/null +++ b/code/application/source/sf_app/component/updataMng/src/sf_md5.c @@ -0,0 +1,349 @@ +/************************************************************************** + * + * Copyright (c) 2009-2018 by SiFar Technology, Inc. + * + * This software is copyrighted by and is the property of SiFar + * Technology, Inc.. All rights are reserved by SiFar Technology, Inc.. + * This software may only be used in accordance with the corresponding + * license agreement. Any unauthorized use, duplication, distribution, + * or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of SiFar Technology, Inc.. + * + * SiFar Technology, Inc. reserves the right to modify this software without notice. + * + * Author: HAC + * Ver: 1.0.0 2021.10.31 + * Description: creat +**************************************************************************/ +#include +#include +#include "sf_md5.h" + +/************************************************************************** + * C O N S T A N T S * + **************************************************************************/ + + +/************************************************************************** + * M A C R O S * + **************************************************************************/ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (UINT32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +/************************************************************************** + * D A T A T Y P E S * + **************************************************************************/ +typedef unsigned char *POINTER; +typedef unsigned int UINT32; +/************************************************************************** + * G L O B A L D A T A * + **************************************************************************/ +static unsigned char PADDING[64] = { +0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/************************************************************************** + * E X T E R N A L R E F E R E N C E S * + **************************************************************************/ + +/************************************************************************** + * F U N C T I O N D E C L A R A T I O N S * + **************************************************************************/ +static void Encode(unsigned char *output, UINT32 *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +static void Decode(UINT32 *output, unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT32)input[j]) | (((UINT32)input[j + 1]) << 8) | + (((UINT32)input[j + 2]) << 16) | (((UINT32)input[j + 3]) << 24); +} + +static void MD5_memcpy(POINTER output, POINTER input, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) + + output[i] = input[i]; +} + +static void MD5_memset(POINTER output, int value, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + +static void MD5Transform(UINT32 state[4], unsigned char block[64]) +{ + UINT32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode(x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + MD5_memset((POINTER)x, 0, sizeof(x)); +} + +void sf_md5_init(MD5_CTX *context) +{ + context->count[0] = context->count[1] = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +void sf_md5_update(MD5_CTX *context, unsigned char *input, unsigned int inputlen) +{ + unsigned int i, index, partLen; + + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + if ((context->count[0] += ((UINT32)inputlen << 3)) < ((UINT32)inputlen << 3)) + context->count[1]++; + + context->count[1] += ((UINT32)inputlen >> 29); + partLen = 64 - index; + + if (inputlen >= partLen) + { + MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputlen; i += 64) + MD5Transform(context->state, &input[i]); + + index = 0; + } + else + i = 0; + + MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputlen - i); +} + +void sf_md5_final(MD5_CTX *context, unsigned char digest[16]) +{ + unsigned char bits[8]; + unsigned int index, padLen; + + Encode(bits, context->count, 8); + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + sf_md5_update(context, PADDING, padLen); + sf_md5_update(context, bits, 8); + Encode(digest, context->state, 16); + MD5_memset((POINTER)context, 0, sizeof(*context)); +} + +#if 0//linux test +#include +#include +#include +#include + + +static void MDPrint(unsigned char digest[16]) +{ + + unsigned int i; + + for (i = 0; i < 16; i++) + printf("%02x", digest[i]); +} + + +static void MDString(char *string) +{ + MD5_CTX context; + unsigned char digest[16]; + unsigned int len = strlen(string); + + sf_md5_init(&context); + sf_md5_update(&context, string, len); + sf_md5_final(&context, digest); + + printf("MD5 (\"%s\") = ", string); + MDPrint(digest); + printf("\n"); +} + +static void MDFile(char *filename) +{ + int fd; + MD5_CTX context; + int len; + unsigned char buffer[1024], digest[16]; + + fd = open(filename, O_RDONLY); + + if (fd==-1) + printf("%s can't be opened\n", filename); + + else { + sf_md5_init(&context); + while (len = read(fd, buffer, 1024)) + sf_md5_update(&context, buffer, len); + sf_md5_final(&context, digest); + + close(fd); + + printf("MD5 (%s) = ", filename); + MDPrint(digest); + printf("\n"); + } +} + + +int main(int argc, char *argv[]) +{ + MD5_CTX context; + + MDString("abcdef"); + MDFile(argv[1]); + + +} + +#endif + + + + + + + diff --git a/code/application/source/sf_app/component/updataMng/src/sf_otamng.c b/code/application/source/sf_app/component/updataMng/src/sf_otamng.c new file mode 100755 index 000000000..c025cb9a5 --- /dev/null +++ b/code/application/source/sf_app/component/updataMng/src/sf_otamng.c @@ -0,0 +1,634 @@ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "sf_type.h" +#include "sf_log.h" +#include "sf_md5.h" +#include "sf_base64.h" +#include "sf_ledmng.h" +#include "sf_fileMng.h" +#include "sf_otamng.h" +#include "sf_systemMng.h" +#include "sf_storeMng.h" +#include "sf_message_queue.h" +#include "sf_http_server.h" +//#include "sf_param_common.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +static SF_OTA_ATTRS stOtaAttrs = {0}; +static SINT32 packet_log_printf(UINT8 *pbuf,UINT16 lenth) +{ + UINT16 i= 0; + for(i = 0;i < lenth;i++) + { + if(i%5 == 0) + printf("[%02d,%02d] = {",i,((lenth - i) < 5)?(lenth-1):(i+4)); + + if((i+1)%5 == 0 || (i+1) == lenth) + printf("0x%02x}\n",*pbuf++); + else + printf("0x%02x,",*pbuf++); + } + return SF_SUCCESS; + +} + +static void upgrade_ota_bitarray_get(UINT8 str[],UINT8 value) +{ + UINT8 i = 0; + for(i = 0; i < 8; i++) { + str[i] = (UINT8)(value & 1); + value = (UINT8)(value >> 1); + } +} + + + +static SINT32 upgrade_ota_dataparse(char *buffer) +{ + SINT32 errcode = 0; + SF_CHAR *pbuff = NULL; + + pbuff = strstr(buffer, "HTTP/1.1"); + if(!pbuff) + return SF_FAILURE; + + errcode = atoi(pbuff + strlen("HTTP/1.1")); + MLOGI("errcode = %d\n",errcode); + if(errcode != 200) + return SF_FAILURE; + + pbuff = strstr(buffer, "Content-Length:"); + if(!pbuff) + return SF_FAILURE; + + stOtaAttrs.filesize = atoi(pbuff + 15); + MLOGI("filesize = %d\n",stOtaAttrs.filesize); + + return SF_SUCCESS; +} +static SINT32 upgrade_ota_firstrecv(SINT32 client,char *data_buff, int length) +{ + SINT32 recv_byte = 0; + SINT32 respl = 0; + MLOGI("\n"); + while (respl < BUFFER_SIZE) + { + recv_byte = http_recv_from_server(client,(data_buff + respl), 1); + printf("%c",data_buff[respl]); + if(recv_byte <= 0) + return SF_FAILURE; + + respl += recv_byte; + data_buff[respl] = '\0'; + if (strstr(data_buff, "\r\n\r\n")) + break; + } + if(respl > BUFFER_SIZE) + return SF_FAILURE; + + return SF_SUCCESS; +} +static SINT32 upgrade_ota_secondrecv(SINT32 client,char *data, int length) +{ + SINT32 recv_byte = 0; + SINT32 respl = 0; + SINT32 loadpercent = 0; + SINT32 lenth = 0; + SINT32 fd = 0; +// SF_CHAR data_buff[BUFFER_SIZE] = {0}; + SF_CHAR *pdata_buff = 0; + SF_CHAR *bufBak = NULL; + + fd = open(data, O_CREAT | O_RDWR, 0); + if (fd < 0) { + MLOGE("create %s error\r\n", data); + return SF_FAILURE; + } + lenth = sizeof(SF_CHAR)*1024*100; + bufBak = (SF_CHAR*)malloc(lenth); + MLOGI("reciving,please waiting................!!!\n"); + memset(bufBak, '\0', lenth); + pdata_buff = bufBak; + MLOGI("Current download progress: [ 0%%]"); + while ((recv_byte = http_recv_from_server(client,pdata_buff, lenth)) > 0 && (respl < stOtaAttrs.filesize)) + { + write(fd, pdata_buff, recv_byte); + respl += recv_byte; + memset(bufBak, '\0', lenth); + loadpercent = (respl*100/stOtaAttrs.filesize); + printf("\b\b\b\b\b\b[%3d%%]",loadpercent); + + fflush(stdout); + pdata_buff = bufBak; + } + printf("\n"); + free(bufBak); + MLOGI("revice finished....\n"); + close(fd); + + return SF_SUCCESS; +} + +static SINT32 upgrade_ota_send(SINT32 client, SF_CHAR * filename) +{ + SINT32 s32ret = SF_SUCCESS; + SINT32 fileFd = 0; + SINT32 tolFileSize = 0; + SINT32 readSize = 0; + + struct stat statBuf; + SF_CHAR * pBuf = NULL; + SF_CHAR * bufBak = NULL; + + fileFd = open(filename, O_RDONLY); + if (fileFd < 0) { + MLOGE("open file error!\n"); + return SF_FAILURE; + } + + fstat(fileFd, &statBuf); + tolFileSize = statBuf.st_size; + + MLOGI("tolFileSize:%d\n", tolFileSize); + bufBak = (tolFileSize > 1024 * 1024 * 5)?malloc(1024 * 1024 * 5) : malloc(tolFileSize); + if(!bufBak) { + MLOGE("malloc buf fail!\n"); + close(fileFd); + return SF_FAILURE; + } + + while (tolFileSize > 0) + { + pBuf = bufBak; + readSize = (tolFileSize >= 1024 * 1024 * 5)?read(fileFd, pBuf, 1024 * 1024 * 5):read(fileFd, pBuf, tolFileSize); + MLOGI("send file data, tolFileSize:%d, read size:%d\n", tolFileSize, readSize); + tolFileSize -= readSize; + + if (readSize > 0) + { + s32ret = http_send_to_server(client, pBuf, readSize); + if (s32ret < 0) { + MLOGE("Connection error (send returned %d)", s32ret); + free(bufBak); + close(fileFd); + return s32ret; + } + } + } + free(bufBak); + close(fileFd); + sf_file_remove(OTAFILE_PATH); + return SF_SUCCESS; +} + +static SINT32 upgrade_ota_addfileheader(void) +{ + SINT16 fd = 0; + SF_CHAR httpstr[128] = {0}; + + fd = open(OTAFILE_PATH, O_CREAT | O_RDWR, 0); + if (fd <= 0) { + MLOGE("create file ota.txt failed\n"); + return SF_FAILURE; + } + MLOGI("\n"); +// SF_CHAR filepath[64] = {0}; +// memset(filepath,'\0',64); +// strcpy(filepath,stOtaAttrs.filepath); + for (UINT8 i = 0; i < 4; i++) + { + memset(httpstr, '\0', 128); + switch (i) + { + case 0: + sprintf(httpstr, "GET /%s HTTP/1.1\r\n", stOtaAttrs.filepath); + break; + case 1: + sprintf(httpstr, "Host: %s\r\n", stOtaAttrs.server_host); + break; + case 2: + memcpy(httpstr, "Connection:close\r\n", strlen("Connection:close\r\n")); + break; + case 3: + memcpy(httpstr, "\r\n", strlen("\r\n")); + break; + } + printf("%s",httpstr); + write(fd, httpstr, strlen(httpstr)); + + } + sync(); + close(fd); + return SF_SUCCESS; +} + + +static SINT32 upgrade_md5_check_code_get(SF_CHAR *filename, UINT8 digest[], UINT32 offset, UINT32 size) +{ + MD5_CTX context; + UINT32 len = 0, i = 0; + UINT32 flieSize = 0; + UINT8 buffer[1024] = {0}; + int fd = 0; + fd = open((SF_CHAR*)filename, O_RDONLY, 0); + if (fd <= 0) + { + MLOGE("read file %s failed\n", filename); + return SF_FAILURE; + } + + sf_md5_init(&context); + while (1) + { + len = read(fd, buffer, size > 1024 ? 1024 : size); + + if(len == 0) + break; + flieSize += len; + sf_md5_update (&context, buffer, len); + size = size - len; + } + + + MLOGI("Check size=%d\n", flieSize); + + sf_md5_final (&context, digest); + close(fd); +// packet_log_printf(digest,16); + return SUCCESS; + +} + +static SINT32 upgrade_ota_cfgcheck(void) +{ + UINT8 srcver[33] = {0}; + UINT8 dstver[33] = {0}; + int fd = 0; + UINT8 mask; + UINT8 value; + UINT8 maskStr[8] = {0}; + UINT8 valueStr[8] = {0}; + UINT8 decodeSrc[33] = {0}; + SF_CHAR decodeDst[33] = {0}; + SF_CHAR localver[24] = {0}; + + fd = open(OTA_CFG_FILE_PATH, O_RDONLY, 0); + if (fd <= 0) { + MLOGE("open file[%s] failed!!!\n",OTA_CFG_FILE_PATH); + return SF_FAILURE; + } + + lseek(fd, 0x30, SEEK_SET); + read(fd, srcver, 32); + + lseek(fd, 0x70, SEEK_SET); + read(fd, dstver, 32); + + lseek(fd, 0xB0, SEEK_SET); + read(fd, &value, 1); + + lseek(fd, 0xB8, SEEK_SET); + read(fd, &mask, 1); + + close(fd); + MLOGI("src=%s\n", srcver); + MLOGI("dst=%s\n", dstver); + MLOGI("strValue=%x\n", value); + MLOGI("strMask=%x\n", mask); + + /*decode version*/ + sf_base64_decode(( char *)srcver, ( char *)decodeSrc); + sf_base64_decode(( char *)dstver, ( char *)decodeDst); + + MLOGI("decodeSrc=%s\n", decodeSrc); + MLOGI("decodeDst=%s\n", decodeDst); + + /*mask-vallue*/ + upgrade_ota_bitarray_get(valueStr, value); + upgrade_ota_bitarray_get(maskStr, mask); + + sf_sys_software_version_get(localver); + + if((maskStr[3] == 1) && (valueStr[3] == 1)) + { + return SF_SUCCESS; + } + else if((maskStr[2] == 1) && (valueStr[2] == 1)) + { + return SF_SUCCESS; + } + else if((maskStr[1] == 1) && (valueStr[1] == 1)) + { + if((strncmp(localver, decodeDst, 2) == 0)) + { + if((maskStr[0] == 1) && (valueStr[0] == 1)) + { + if((strncmp(localver+4, decodeDst+4, 2) == 0)) + { + return SF_SUCCESS; + } + else + { + MLOGE("FEA is different !\n"); + return SF_FAILURE; + } + } + else + { + return SF_SUCCESS; + } + } + else + { + return SF_FAILURE; + } + } + else + { + if((strstr((char *)decodeSrc, (char *)localver))) + { + + return SF_SUCCESS; + } + else + { + + return SF_FAILURE; + } + } +} +static SINT32 upgrade_md5_check(void) +{ + int fd = 0; + UINT8 srcCheckCode[16] = {0};//md5 + UINT8 dstCheckCode[16] = {0};//md5 + UINT32 filesize = 0; + SINT32 s32ret = SF_SUCCESS; + fd = open(OTA_CFG_FILE_PATH, O_RDONLY, 0); + if (fd <= 0) + { + MLOGE("open file [%s] failed\n",OTA_CFG_FILE_PATH); + return SF_FAILURE; + } + + lseek(fd, 0x100, SEEK_SET); + read(fd, srcCheckCode, 16); + close(fd); + +// MLOGD("\n"); +// packet_log_printf(srcCheckCode,16); + + s32ret = sf_file_size_get(OTA_UPGRADE_FILE_PATH,&filesize); + MLOGI("file [%s] size is %d\r\n", OTA_UPGRADE_FILE_PATH,filesize); + s32ret = upgrade_md5_check_code_get(OTA_UPGRADE_FILE_PATH, dstCheckCode, 0, filesize); + + for(UINT8 i = 0; i < 16; i++) + { + if(srcCheckCode[i] != dstCheckCode[i]) + { + MLOGE("ERROR: BRN MD5 check error srcCheckCode[%d]=%d dstCheckCode[%d]=%d\n", i, srcCheckCode[i], i, dstCheckCode[i]); + return SF_FAILURE; + } + } + + return s32ret; +} +SINT32 upgrade_ota_file_IsExsit(SF_CHAR *fileName) +{ + return (access((char*)fileName, F_OK) == 0)?SF_TRUE:SF_FALSE; +} + + +SINT32 sf_upgrade_ota_init(void) +{ + SINT32 s32ret = SF_SUCCESS; + UINT8 j = 0; + SF_CHAR filepath[64] = {0}; + SF_URL_S *phttpurl = sf_ota_url_get(); + if(phttpurl == NULL) { + MLOGE("download url is null\n!!!"); + return SF_FAILURE; + } + s32ret = sscanf(phttpurl->url, "%*[^//]//%[^/]",stOtaAttrs.server_host); + if(s32ret <= 0) { + MLOGE("String matching failed,please check download url!!!\n"); + return SF_FAILURE; + } + MLOGI("host = [%s]\n",stOtaAttrs.server_host); + + s32ret = sscanf((SF_CHAR*)phttpurl->url, "%*[^//]//%*[^/]/%s",stOtaAttrs.filepath); + if(s32ret <= 0) { + MLOGE("String matching failed,please check download url!!!\n"); + return SF_FAILURE; + } + MLOGI("filepath = [%s]\n",stOtaAttrs.filepath); + while(j< 64) + { + if(stOtaAttrs.filepath[j] == '\5') + stOtaAttrs.filepath[j] = '\0'; + j++; + } + memset(filepath,'\0',64); + strcpy(filepath,stOtaAttrs.filepath); + s32ret = sscanf(filepath, "%*[^/]/%s",stOtaAttrs.filename); + if(s32ret <= 0) { + MLOGE("String matching failed,please check download url!!!\n"); + return SF_FAILURE; + } + MLOGI("filename = [%s]\n",stOtaAttrs.filename); + + + if(upgrade_ota_file_IsExsit(SF_OTA_UPGRADE_FILE_PATH) == SF_TRUE) + sf_file_remove(SF_OTA_UPGRADE_FILE_PATH); + if(upgrade_ota_file_IsExsit(OTA_CFG_FILE_PATH) == SF_TRUE) + sf_file_remove(OTA_CFG_FILE_PATH); + if(upgrade_ota_file_IsExsit(OTAFILE_PATH) == SF_TRUE) + sf_file_remove(OTAFILE_PATH); + + return SF_SUCCESS; +} + +SINT32 sf_upgrade_ota_download(void) +{ + SINT32 s32ret = SF_SUCCESS; + SINT32 sock_ota = 0; + SF_CHAR data_buff[BUFFER_SIZE] = {0}; + SF_CHAR cmd[512] = {0}; + s32ret = http_server_creat(stOtaAttrs.server_host, &sock_ota); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = upgrade_ota_addfileheader(); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = upgrade_ota_send(sock_ota,OTAFILE_PATH); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = upgrade_ota_firstrecv(sock_ota,data_buff,BUFFER_SIZE); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = upgrade_ota_dataparse(data_buff); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + sprintf(data_buff,"%s/%s",OTA_UPGRADE_FATH_PREFIX, stOtaAttrs.filename); + s32ret = upgrade_ota_secondrecv(sock_ota,data_buff,BUFFER_SIZE); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = http_server_close(sock_ota); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + sprintf(cmd, "unzip %s/%s -d %s",OTA_UPGRADE_FATH_PREFIX,stOtaAttrs.filename,OTA_UPGRADE_FATH_PREFIX); + s32ret = system(cmd); + if(s32ret != SF_SUCCESS) { + MLOGW("remount sd \n"); + SF_MESSAGE_BUF_S stMessageBuf = {0}; + stMessageBuf.cmdId = 0x0113; + stMessageBuf.arg1 = 0; + sf_com_message_send_to_cardv(&stMessageBuf); + usleep(500000); + s32ret = system(cmd); + } + + + return s32ret; + +} +SINT32 sf_upgrade_ota_filecheck(void) +{ + + SINT32 s32ret = SF_SUCCESS; + s32ret = upgrade_ota_cfgcheck(); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + s32ret = upgrade_md5_check(); + SF_APPCOMM_CHECK_RETURN(s32ret,SF_HTTP_ERROR_REQUEST); + + return SF_SUCCESS; +} +SINT32 sf_upgrade_ota_param_bak(void) +{ + int fd = 0; + int ret = 0; + MLOGI("\n"); + SF_PDT_PARAM_CFG_S *pCusParam = sf_customer_param_get(); + fd = open(SF_OTA_PARAM_BACKUP_FATH, O_CREAT|O_RDWR, 0); + if (fd <= 0) { + MLOGE("create file backup.txt failed\n"); + return SF_FAILURE; + } + ret = write(fd, pCusParam, sizeof(SF_PDT_PARAM_CFG_S)); + if(ret <= 0) { + close(fd); + MLOGE("write backup param failed !!!\n"); + return SF_FAILURE; + } + sync(); + close(fd); + MLOGI("\n"); + + return SF_SUCCESS; + +} +SINT32 sf_upgrade_ota_param_recover(void) +{ + int fd = 0; + int ret = 0; + SF_PDT_PARAM_CFG_S *pCusParam = sf_customer_param_get(); + SF_PDT_PARAM_CFG_S stcusParam = {0}; + + if(SF_TRUE != upgrade_ota_file_IsExsit(SF_OTA_PARAM_BACKUP_FATH)) + return SF_SUCCESS; + + fd = open(SF_OTA_PARAM_BACKUP_FATH, O_RDONLY, 0); + if (fd <= 0) + { + printf("open file backup.txt failed\n"); + return SF_FAILURE; + } + ret = read(fd, &stcusParam, sizeof(SF_PDT_PARAM_CFG_S)); + if(ret <= 0) + { + close(fd); + return SF_FAILURE; + } + close(fd); + memcpy(pCusParam, &stcusParam, sizeof(SF_PDT_PARAM_CFG_S)); + + ret = sf_customer_param_save(pCusParam); + sf_file_remove(SF_OTA_PARAM_BACKUP_FATH); + return ret; + +} + +SINT32 sf_upgrade_ota_env_set(void) +{ + SINT32 ret = 0; + SF_RTOSINFO_S stRtosData = {0}; + + sf_sys_rtosdata_get(&stRtosData); + sleep(2); + if(!(sf_sd_status_get() == SF_SD_OK || sf_sd_status_get() == SF_SD_FULL)) { + MLOGE("SD is not exsited ,please check it !!!"); + return SF_FAILURE; + } + + MLOGI("upgradeFile:%d, bat:%d\n", upgrade_ota_file_IsExsit(SF_OTA_UPGRADE_FILE_PATH), stRtosData.BatPer); + if((SF_TRUE == upgrade_ota_file_IsExsit(SF_OTA_UPGRADE_FILE_PATH)) && (stRtosData.BatPer >= 40)) + { + + ret = system("mkdir -p /var/lock"); + printf("mkdir -p /var/lock, ret:%d\r\n", ret); + ret = system("./usr/etc/fw_setenv sdautoupgrade 1"); + printf("./usr/etc/fw_setenv sdautoupgrade 1, ret:%d\r\n", ret); + } + else + { + MLOGE("upgrade fail,please check it \n"); + ret = SF_FAILURE; + } + return ret; +} +SINT32 sf_upgrade_ota_reset(void) +{ + SF_CHAR data_buff[BUFFER_SIZE] = {0}; + if(stOtaAttrs.filename == NULL) { + MLOGE("souce filename is null\n"); + return SF_FAILURE; + } + sprintf(data_buff,"%s/%s",OTA_UPGRADE_FATH_PREFIX, stOtaAttrs.filename); + if(upgrade_ota_file_IsExsit(data_buff) == SF_TRUE) + sf_file_remove(data_buff); + if(upgrade_ota_file_IsExsit(OTA_CFG_FILE_PATH) == SF_TRUE) + sf_file_remove(OTA_CFG_FILE_PATH); + if(upgrade_ota_file_IsExsit(OTAFILE_PATH) == SF_TRUE) + sf_file_remove(OTAFILE_PATH); + return SF_SUCCESS; +} + +SINT32 sf_upgrade_ota_deinit(void) +{ + memset(&stOtaAttrs,0,sizeof(SF_OTA_ATTRS)); + return SF_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + + diff --git a/code/application/source/sf_app/output/lib/static/lib4gMng.a b/code/application/source/sf_app/output/lib/static/lib4gMng.a new file mode 100755 index 0000000000000000000000000000000000000000..a17a66de8bd946a979e389cfbff39134a9594eea GIT binary patch literal 107766 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 CzE&Ur literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/lib/static/libcjson.a b/code/application/source/sf_app/output/lib/static/libcjson.a new file mode 100755 index 0000000000000000000000000000000000000000..d876e6d7537a738b8fbddcb3d2f187530058e6bb GIT binary patch literal 39756 zcmeHweSB5Lng85-1Az#NfC34{O9D#07{ZIZAXW ztka2$T2-2kUS8MInr><|%*J%v!ltJ6tvX&+*HG7HaxSlHyL97*n!1*Sbq&pRrjVt{ zme#r}(ru|F&21)|Ow$lcp+K8`e_7+Yrj`xKwzj%jJGpY>x^;Ce!L+3? zfG1lor=;DkRdsF2wJEmu<>}(bjueU2{WntyH{UZ7p6f)4G;A<4XaVfMz*3x$35zShc+8 z{etkTxUQqE@>%Eo!y;;G$Nm11)N`Ix!<0UOh~^_(ghb@|b>CSkSbgIoV?L z+8{?vC05$xO~LluJH4!I7G_)XclK<=X3m*2XNH`769qSZadCAh6v7m&LP$&zeoTnR zT4nm6S&~cza&%)Z9>p11S&uUOUJ#`mD**W+p_Cs zsoA_lCM9Cw?l}I2dO{^rdplC`RA=RI=y^8vY*#u*aUYtQNyPCtjyy%}W2=dpR~`56 zBh~j;zTG_#@81i@Ru4msw>$@>t&rVyi`GPx^d&?|m(+-MI-}RvEi|(aB^RZRr?y|T zJJBU|6(xguKT2&%?UuIfN{y`^A?=ynscOc074?`}gN9*=aACqtS=le8GqJeWl`3SN zfjAiT^IJO?S|+th%dPah!Y@Md50vJ-NzMoV*rTl#DXu-ZzMz(QRkJu;nnN|}|l$Q8CM>$A# z*LLk2OOA*zuEf3Ni z)u^hX_Akc1@J1}Q?ocdV7+ZTV^zCKGOOE_AiaH0Ko%93ip79f1%y+UEvFc(|dV)HQ zYtKJAB;2=QR8>KBVRL@3iETT+BwE-k_VsOm@7MKhxF9zCAZuBGT6Us7g;jC*S!d;) zuZDVIMO-GQCNO;SnF@9m=Gdj)=;Y$uoKtZ?w-lm`R}(z{{7s|2q6qX3XI&=VnqXlbO_z z;@8njcch+WN#U;+Qpe6j2(6lsJrjD0{hxgD$^W_#ra8SV9(9D3v&gCZQuv`5{B zKC=q<`AF+b@gA0ZRg`qV$KZ3Xi;|6y=!Cb8s!}85s#G~-2Ek&5kl%syT1c=Tg}Oz_ zmyqx2quC`xUS5*!7K(3{3mhkEq3)Uzq}B-O{yM~^&|W~%Cg zqIf0b(efBSr=ye|>D}mON_P0C$QJeXq4XgrW1Q46G_$Z;jT}MzJt^XUl;SA31C(=| z>bF~Vu?5>vF2@rQ8>MY_8mOr^Irn4iR(+!XH>y@_Wp`N7e`Y@M= zW_ICkB=*E>oUQy`n%(tPIW|0-=z#v28hBW;FV&S4CAS|h!Ki=x@nZRRqWl{z+mq@_ zzgjpbR`EeswksW;sapSdvM>Gg?^Z9#dzCb?WdD&LWO;YxlDJG+y=2aTuJquU8Q{i~ z!+<&wNEwaPna!k&+E>Raj%>qSXl7CSM%>?xdxJkW8JGC`k8IBJF0mwgm4jh=}Tv7GW9pcA_qgVMrZYA>Yx6dXc~MV zEaUs}H(EAYre^o3y)P9xK!oDh>zI#&oa~VUS;eb3@{d_x2bG&X7Kdg<>GE`Fh8&UMVIn4u zJd0NEOKgRusM(P2j{4=}Gc|pwtHytrU|+tiH(b)UvAjM5Ed;#uJJ}5MqeqDk9>}ha z<-J}UTirb^wz7L$@9Oxtn0Wu5tXiRnegBGe##Q0|*F#SF<4)Yo^Q^;vQOA2g{|_$A zpW{DD48aH!!_2_@VYr{H?+b8$mcAd3`*HeyDDFq;`;Pi$sOvC{bi*Qr)${7x>(!{= zx3TXA5u4hL70nGD^=$Kw`gnb3;3~5HhI|SU+HvNf*+-UTby2S9U-bjCoi~ zOn^rf;L7D`YzM9aSEY}qu`I6J+Si+beq(y#>0;P4j{JN^Qe$BsdRsa2lGB$8%X?Zr zRPu1IFW-fgTwn4lT9;w3shSMwCWV)R7Pfb#3!7VdyV5Ji?@6vEnyl>?P}{3e+rrr8 zdTsqSd}t~9lo49!@_iJ�p95V7Iu5iE^bF7z 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 JRzf59e*h1!`Sbt) literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/lib/static/libiot_hal.a b/code/application/source/sf_app/output/lib/static/libiot_hal.a new file mode 100755 index 0000000000000000000000000000000000000000..2c93b5586c11d873a2e9210c995d3c7df3c99ad1 GIT binary patch literal 55898 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 ILcQL901DrIfdBvi literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/lib/static/libiot_sdk.a b/code/application/source/sf_app/output/lib/static/libiot_sdk.a new file mode 100755 index 0000000000000000000000000000000000000000..71f12ca7dd999a484f8bf5aa53fdbb0194c634c2 GIT binary patch literal 450448 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 z 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

2`hbl#h3$rIY;cvhM3h{!KQV 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

ePGJ_#R6lrjLQ)}~kG*o-lVLjX zbkRrObMLHnjDd#w_!yD4@E*SK)RpMtJ+|TUj*I^AknH1K5q&&+#7%rAw{;u+MjttZ z_~c13q_c3><$0;3(vLVcK7Q)_;j>M5`U+G3F56<+JMk+8}y`u-oj^q3TJ0)_3t9b^%U=<9k?d_3HPyAN_5^O!ewWk5R}sv9s5# zBf%$yHH**5u;-B#$KJ5p}}6a@RThVXO^jN2KMfX#Fh2pC` zUDnL_E)l)_mmS{&5%CqCnj-R-@s-5)n~3--Pk&wHZ`fB7-+5|aBvhV-r*07W^L!=o zl|{r?d3uq^-&a$f-&XN`k!P*)bOYW*(!ZosG5jlu&mANCTXS7ZF8b=8?P?Vt=H+mf0Cuwr;~Va2b**k+HI4tGQ47q)vU3wcVLXg!1~xM@m~+xo6-`YjoagU(MHxeq=$w>lnP;iBa|G$ z>0N`iR}v}Fo1G6+M&uUzNTVV$FCi|97h}j|^v5TPfG+gp;QrH@`CGg~Mz zWbGI$%S@RFG3%v~cW4S4$$^Q6rm8U8BtgR?=3pY>uniDydqif3zGGoOU~H7=WH@ap zL}lM(P6SpnOvM&%Cd9;0h745rx}|lYxg(QQbju$m0kiRluxAF0vD&IcujS0pAp;W; z;UidQDL-jKBfR)}jn`y}A}mr-?tN4snPXZkF-IB2e2A%(M0}jeGY1iog*PnsRc;}She-*rVumV~$y3)><)y0rSZVYotVF|EN?tx`VRGu>3wuVx z1j4GC=@y3`eI-5?4dvLH#^yS79nC9XCx;%oWzt?I%TTJ#GII>wL`7-OEQw+SY_SoE zXctrl#7PpuU$)gMABl?z+!YfR#Y(UZDnbIjWD-I4QiByEANc8-Xp>*bWmPS}a zL54c8AXsLZ`fjT-9BHA0afO~rnLw>EC=h!5VMGk46OA2-e>hO5aY>zF@}bQ#Os>{d zFEjf_lN>qLB+DKJji=~Q#_B|xUqV#6rI$907FGt~EJN|eVgh)qFoq@HJPhH1zDmD{ z2)YHQEHO{&<>aebour0P(uw04*#HuCclY)gp>M1_IIT<>v`%ORfn%N(F~fRC%jeq+$Ng*b`#C?-C?51 zFNnh*;biBpH(#i5)Z=xChCKJu@@z@6|oz$OX zqRDSF(G1W1w$e%c$4oT&*0Te+UslVL?>EuZ|FVfDztcpM&;6^?sq!(=4p=Z`WKy%IPd^aw>$*Fz@yVbGk5(D82v?ZWdZ*NVgnJER=<9;(700$vH4>r5H{ z2_Wrkcoh9t;FF-45Ap{>_d(D)JZ*&k(L_%GJs8h>hLWESIv=!7&o@9fgVyEI1bT-_ z{=1-$gC3^B)Aq=46uM5&6QHjKouT;8gI*09TaHBf{sr_t(3y&U7xZVKhb#JH(3hb- z(ecAO=)Q`zgIu$OD2;izxHeDEr7%)fOE37^k)B|oXIkib&|DkH`%Zm#Tlf!IXs&ho zJ!D&z{O>J%-aG9We}9xc>lf<<_4D3oNB$KSdXa^`!9w2xdNktLhOpGP*}{Jw^xNR? zQ~dWqKZNV3qGNIIv}634pl`x;48N(*XW?IKp=&Jkofi6s7Wz>O{ZF9lP+zW8@g1}9 zUEn>3i_fVjFZ|Yy>AebcMlALw<2U)=weUBCrv3Bh75_C0|Bs+cP7i;4fRg-@F(JWD`_KWgD~QCKzlC(X|Yz6;3be*)+O z;OqR&x9}T4KZJzp@b_ByKL_0({gLMX#=`#u^i3xIMZtFo8UNQnb4-wH1Zf+*8uX2z z*&mR;2{gwj+5VIMG3a|iCo6h4XpWg)py+=E{ZsJSMN-0#+<6d)oTI(MM zn)ZO$g_D07XpWa_`LBciCHSZUg5Lm|x<1yo14trtOqe&^mlG=y9NR_gXUQvnqC3= z7ohe1-+yS=sBQu`P25w63{yRJ)n6$gU(+P0&WEDR`E{& z{Rw_+dA>_NXVSLzq`neYLA3);~6X|~zG}{bK9|awQ!pKm3+FIedGJXF?fF5q* z&jDR$;ppgubzDq%8;kPcIa?o4A z*Y&do^d8VUecuDk^Br{k{0Znkf<_jFzMY^?g9ZrtHT;M{Wk50n{T}EcpmqBG19Urh zsHTFim-vUT6L(tpU-cNE#kG^!CU#vz8=f>!QfDLLGpu*uRs<50s? z;U_zXX~9O7nvk(|Qzjzf44=r7=?M4JQ*{wRzt|L(yf0db9vF=*6*&)N8n09$dO}C# znmG)a+n35!P+goR9g$Z1!#Bo+g^w_yFUqfPi~fB}m~KR97OpDVESyYGA41X9g$;0r z)pC=%XhJ4+vLvI;*qKWz8ow7Mx($d7t~ny0bzV=@_CDwOR3^jb|KKMk1*05Apu~IU znDQWIkuWu&&neL5*%&^BsJu-9^<<$AAk5-hJWb-^bB3yv8mbpA4el;839BiBaMfRI zI#I^(pP6b5i&aj{g`GMbSrk!c93#|(=7-e4d8DG?&5%=iVJf2YOob){qE&lY6uq)d zDy-9xVF>^e&ll1jny2U`2cek`t$?*D!q*hBNL=_Fq$$3dgW<*=VuYnENS7{WIJCN67P*0 z?l0_s7ne<)HBFe}XELR_aNFup0>N^1xUV!2Ps7zw;tw*z!$cTe@0A^e5wyV`ofq!Q z1XxY7pG_i?7jCD$cYZi$+SGZaU!Qta)$GzaGs~kEO}IpOXl2(uN`XpFxO9oK^BzT9 zu`KeXGfL-`M!Q|o+I+aQ)nt5>SS%tsJP%zcuAEa^rR}1_L-TsKx_&kZ%`+RP5BC#> z*R_|d(veo@d*_F9dNDKKhfuFZ4lS7!p5BF6j=|h(2zg|A0qVQrAXr-W)1ugB< z0)LdM98E5Id_hgUHGQRXt}HJutuo7LO=g?@I=xlpv#zYHD6I-+FRBnt`Olpsm z_O~P4c+$17Z2`0+5wnRHzvR55h*#liBEtWei16Eq2)~cG2y?W=>tWk~7=R5rBIJ6A z^|1A+XwJ2g<{ApdmrcY~LVu)pw!&H>;%g#8&uv7+C(blLe49ukK5@3e5^1A=@?3jC zy_|!k-a`sM0aCx+Au)vr`C&xpFCap{j|jaBlz%M|>0PYo6^iB>4#u;d2;DrBnfhN) z__D%IBJ>|6`Z3q4Xr9T;_&r4M^NEPRh=};-D1ULLK?BMGG~;U}BEB|-tCZY>MCjk9 zXwLDH=6oFEIYn&3I4j2TUEjp`FR>YO=S1YMfY<_?6GT)xafZQi%*%pid<%$(|5`=+ z6*d8x?;D8Fe;X0D_cjorcM}nMA0tBV>qMl7XBbfaUE)gA6C&jQN`$;P!vOMJ%ffhh zhBDJ3&M-juDWDm?jQDNX4kaRdEfL{4kH`4hfee2e5#iUkL4GuP?QT1@sFoJ;ww@(L*YCk!qpOy-y0N78y8H^ z^+54ICqggn z!chJ^B4}}z0pb}2n(>s-A9`mI5uZ5Q0MFGz()Suh8xi5e83%Z-ZY7Q9it}(x?}J3> z;XEAmh_eo$N1Sy4J#Wx|E!sIE^n65wo>N5V;aV)};n@e&GYm*QV~EgGK!lzm;(bUT z5qhp8LeD}X^l;4<_1s8=o^|wxo*xsTXEPCcwiADZ^bw)wbt3eLvl5_(YrCjNoRt7Q zPE1@;&v``XNg+ayhxh=}M}(d!MCd6ZLJ#NdsE21OGd<$W1nBt=`OtF*5qj1THzIvR z=y{3=J==-U!?j}6^C}T~j?*9EKT(*N1R8o%iMY>Wh^QBniKrJdhz}thiZ9MiKs*hK zzJUmuYt9(YdLrW4Mt|simWcTF6Pr+8L@d&JpNMeBiAe89M5LE%)2N4MDNv6aNIfHn z(34MWLU|E?f_8uiJy#Q<=Q<+va19&vv=O0aHT|Jy0}*;2BSOzp#7B`nBJ{jMgr3)l z(8INE)N_moJ)Q*2<$f3GAbt<+^?xJVNFO2(+TnFUxC`+YSuqL)h4Pw=HUJ)I1`WK@ z8I(g;pw_R2?EAPmp=)xKr5lNh@(vPky~%mOW0+hD!BOri`BVHQkJr}}qUeQN3Asy| zVC8hY(?Ih#_0m0pjG2?D_00xPhoRgK7J$iVo*#b518RtLl*`iuP|Fc@+Q>czIj;9a zGcL|4WBDcFVv=>4;HME7fjMnc0<}KgqA)q1DG}glISef}Hnomv94qV{!2)X^Hd%9W z@?n{ku5a5&`(%cKwvqawHgt42vXc+JbIdqtkLx$U6-cN^^&9S{X|6zA#nt{lcew&F z6&w5?105BI{oP%(egrG6dzse<5O$yn>*^n0abdu4_wzSRi>bIK@aHaP#m2xVUG|D2 zfj{X`45XaS?^m;0T*o5Ofszl#C%oi(T|Nua$@Q?fy+NAy7tKSEW_Ub8L7IHr!XQol zbWI{Q@|RlZAc^$EDS~y#7FIJ@Pr_5{5ZcV4@v?1lT%T)p)GqbPG;@6!ABW3v<>Ml) z);9j)tsw@MZtH-<$zi_*V!S*lJI2@92F)k)W=bCv6KG68hvZrI7 z&28X3)PI%>+cAcxT(mauG5AwXJFU;!2JX-T3aOLMi;KUBbd)nS34%xdL|i%yei|?F zkI89XIsD9R7Uj;R&H5a2UMOK1u>D~^m@jLa#eERN;jf*J*V<B8{_gvd7zbyQ)HY=vW1zTSicG!F=+>gE2+$JUMoa~7W+KzT#MB50??xDiMhT%@y z!}KQYG#~?Co8%{Txc%f&&tH_?o1~r28Sa3#bDSyo3|r9Q2#nnAoIWTpsKf40@ik3T zv6J}~+2y5b?bsIR`y>5iTa%&%z$HJ;M6(FZZ5R247QWv^lV5A18NSU#lYgU$CV!oU z4w6W(ZtIu^nc5IHvaK`slC1ZAw{^)vugo*swqYUlqP~v@eGxADlV4=v^ZC+_&&M^I z0FqvYYbq`sK2#Qx&)3B|T)YR=zZR$+!#{%SCS1HH5p8d4wKmv_XGkn7TH07$Yt%Qk zw(+S7`N*fNs=guInCrB<*4cfW-A*-_;x)=E=T%kCn_5*)6-u2l`KnnZ*vJ=Ra$c8# z1Jw<+n9XPY*axt!aABd}C?Xcf<`co>{Uv_}X)ILqE1G?W3z=uRkvK~p(j&+>Q+NV5;>bd~_ef24?iqN4y$i8saK812DN9}aHUU)DJk&bfb(x?1R zNQeIDc&&X3<<6x~Nrr->xY&mb#>Mopj$8Yb)95R9!CyNaueDEcLP0NmN=u*`tL#*_ z(${c=Wx~TI&*_F6T`9nFa z4^5j`E~(#0`l>tmIr#(6DZIh7YGI zd?6jMiBtT&ZHW)Bf~7xSr|r^`w~etyoyIWR2_qpE)~K>ze^T0Be8zWvkL|8q-Pa6A z@7&e>jR9Gmvr11N_*KXLj;vJMxVqBh1Fnwv)Fgkuj$iZ``xd758`1AA+hw*Kv$e(o zKTdTxnkDSm#t566w%y;8AG^FNwcB9W6T(VMRB_*Yvb;>8Q7_ zetKY_{JB~q-eOgL4Aw_ImRs^j zF=BdWa=;ih?ZB>XV?asg^dvW)jF)>1H{;Is8`+n4!e*gcKCzj22IIPI=S{x$v2L&Z zjqM2|V&8nMd#XKV#Ql3GOiuN^yZzEY<#B)Fz@9{J@p1cL8!#PK+#u~ZvOQsB9HkvG zBk$k)SoZ|SVBZnQ+r76JLEc?-++l~jyYnr>z314;Tg<6HxijYB%^k+2gWvv9hmkeP zm(=6jwr+t!PIo2k^dqe6ZCeS- zv0@$0NWoO@A9j+trod+xB)(!KOstYTpB*lqxz|2C=^6-H-a5N2eg~ zq`&K9NqwzzH~voUd=`HvcEb8qlH=Ydo|E}i+pGLa> zG<5)KQ@gM2>2E&0`03=pwa+n?F|fcZuq4B`7|*e74Jog`C)oPRw9>YsSF{@A1F|*I zAt!>bSdD;;u9O*vr=MH1UMQ2{# zrEM~-3wq1%()A{q?~aLhPt@VbN;1*puQt)-uQSo)b3K4`>buuOYYwsR?@Ve7xoBf* zAujcaw?^?ER0syY>-b)z9p8yB(FBn67z@q!o~gJ>a4~$bh0pH_ep^1G_zf0*3usse zH<}gy4htXCVnN6FAH?+lAAzg ze;D-L;By?8{GWs7K3_yB=sgyBHRh>b536b#n^t0_eREw+t2|bvdMOTX(K~uV`%vWG z8%oQQP^`zA1QlWvP<3-NKGAFI+6=vKLx!$zZN#^HD6Y8;P0jTUt&5D%#-WfPKh7n! z$P_HhGb9qgp){?HRnQai13^EqLVn0kYvYm-&4uXIHFZ^3f^7~dZQWEgR4)_D_hmA; zpNTsOnwskt)thuKZfR^#n_8CE!x~$S$s?Ft;n%ouF^ahgLdy)3sM$LhK$dSPrHh*D z>Y|-NlZ^Z9!iR^Oh>y_`M0oPK;rK+Y^5=6y|6>Y2BBmHd5$XrWDY%A;X9mw9LLbi! zA{`(?FY6)cHX`(}P2-&54$=t!g5tkSM7#$T{W~JUzpvoBL6ZX^oX@o zh-W%!q=WV=7_VQ+EmCw75qj7*QqLCB(DMQjdU)Oo!@WU7dVZ(qV?@Y(r05cQu5qKP5BoTzO4K|Cqh1!ZNP9m^F+{BDqKj+#{E z>7oZ^=~xt$?@P`L8HUNlMMr&RmE`gInnKFc{T4!~&OxW;%HYG_+8r}1gQw>4c}Cir z%yM~}Fv(FK#SnC97}nXxIu4(+&40Xwg6q_gL012?j#Yh#wJCw1_K@7z-0?Yb{6PNg zYrNrq$ExI*v8gD-%ADn|>teoH2*35c`5!b^#eJo9&Hp>jX}QxO63v^q@49*DtxoWH z{r{=%jLj|3gWjUy>8stz%bzHZ(K?4Q@=Yvsm`spmoeeu3iAGw5;lVffw0C;iHa*}= zt$e4awSDM}RKLexbSi0uGjpP6BF;9#SvZgLOFGBr7vI{0Dq?(-z_G0^#Hly(WD@zc z3qvY>mM7r1t!7$c%VNvr zSARd8x1!^^O#NVgJfOnZ`GalO1Z;W9ojl!Fo+?v$df!}EdCXcY8>?`Y#jUk(HP$+| zQd7dVZ}d3-!e2)Azjb~p#v!S$1Q)+)3U=Bu`^`+8k?9{9SkmFH59L^vR?=>K+vnBz z3--9gsMHBHA59(Joyoqtwk3OFeEm<@4adDk2IFyT{IJ8*W*d=u!0w4z)4y!$sXKDx z*1)jXnwTd>_zJ~6NT_h4{2%bd<7{4MW?UJ=Igh{J#9Z4vv1{HF>AV7QjA2A@2^E8P z+I$N{=r|Gj2~VsD9VU+SsQug_D_6n5>bv_B7?~<8vdbDO4KH(Y~@Le&=-6~Jkty?5UZJ zt*!Jgp6T|{&UdW=CcgV*Xk+g3g)KEWrLfLDr>0bHFU0QCfLXFi zM;Fuxo2jtkSzEPec|#4qV``Sx!^SvP*wi(c$e@0c-||qbCf_C*=~pz4BMMsm;aVxP zi?;TN_khkk47NqN{*KxbSHr_{~7pf4(zQp7Dj8LyQTL=Jx>Cj)n7`;{4JO-)TIhWD|wF zQ;grREt28&R|P{b{lS7#G+v@jj^kct=fGFTznDCz_lSi)VWB^@(D8`!Zus%tn&UVZ zn36z!w8f|$=}DkD_B0z8^DJ~7=u%vqSEu}P3!kW_rB&5$15bktS@s6C$kI zcqc?y$nnB_kg4seZdp>bw61zZoz=6ht-e*BNvs+)9yM$VC>lLEQlpLm)-9uMX?X(h z+@*DOO*31>klQ>Fq$Fqn!rV~mu$ER++V@aPQbKL3jse45JT8F|N#&t~j&-7!Hn!A- zx(Gpq^n@B^9Y1_bO|iLw))KUAy*>WtFYiHWvZyzGpVR7uHowP%aA~c zo+LtVEaKpq!)_uPs}aOYWxLGq1)%L{IwlhlzK{t2D=CL``iWkAv=fnjw%1JejYP<; zp+EFLLqw)uAtHTjx5+>5f8$t@96I{@oRxeV(yX0s-K}Frt1;%W ziDd~vfanY2fhZb5qX>lC1zlPPJ@ju>ov<+@+GAyZrk$2U6%hJZujweaTK*J&88@%5 zDbz`yfdniT67mma=%(S~Z|bFc26F5twbS}$!$XH5kNY~!PV@Zm1glB&D0ePnOP@n- zH7_I(1M9D$pssxa~vPY@#YoC#VmdA2dI@V zD#35O^YE2-@lG58y*j|JxIuRD%@iZPXnONMxziZ-+&0e2X5jSCRGfGgFV4p;!6~B& zoB5qFq#|{T>9Jeu{L3AoH#vjQ_+P-oKM)@P9cpGLN{*guxF+|VOyQB#aL@| z$5$}y+aFxWlL*gb?~a*n%hc2)te?>Z%(Ct+ZU0sNe_NS2{+}un=4E&A{-)sm#s=@N zJSR4>B4vyH2?y@4V}*Tf+*WxyBYX^e1Ha8o$H)< zmpL8a{%h})UjVIMi5(;?c# z#ESbpiRJyv^r)8bJppZd6Dl6WnX9o;IP7naq7y*3AZ$qRJ*Kzv8U4YTX~wX3dgisq zVtpV_hkOL*l;XVCAsM!#6 z%$xlCT2JDpe^+BlU*+@n?VIo_JCZ{+SX#cIs(5CVG&NH^qjG);4FAlURa!i+v?MAQ zc8QdLZYgAWg{c4kX#GB=%iw~*Wpcgq7dq?7vFOfPRzU-TE^>@3m{B1UIp)bP zqmbj6m)SY+6*UzeOmzw_j`8?`+VQ*K7FmahKu1p0%}M8$C?0= zPGe-sk>)xu?MU;y675KrS?FslG{?YpLQbb|vxU#|M_x1Wu^=<(sGr~Ae=za$gLPA; zmup%6!^HoVg}(vx5a`tLzi8oq2zs=MpKQ8ijDHGfj`8X8yT-z|p5L(n{9l>$J!_Hw zHR#`)_&mEsJH~eg^q)=q!KMmI{ut0)TX!vf^M1~<@M#xFJIb#Gz04%P)x!U!g+2=U zS0?#SE&Qb5vn9)a1n4ZJS*K^Jg@3h$=CgZ?Nq((`zr#ZR7WCVY*Z1$w7JfRO?T=0T z;^4C`)5o&|`XdiIJkJi%j^(ojbe4%vyFc2Ie-iZNCVmoMu#_X8=X1$4O50DiMR)LQto@1q^%@3GK70eun5bOCq_ zzsthkZ=sJ^=s$s8j_|sC&o?z;jBgU?yTSJ>{R=F7p4Y)MTXg-o)570uq5sK3AG6S( zS?CPD7%Rv0lvwCx7J7|^ru`r782+$@K4YPIK8JRcpJJh}vCxec`g<0dXT4}geY-96 zn-=;n7CMEKGs-c1zJ;D=p;uVwH5R(VLceaIk6Y;Y{yKK~JYH&{i!F4Wg}%W;-(#W8 z_6F2AJQtNNt8R*z*ccaaaDjJRzG?hinh!olGx|Y0{h{|vbNDcm_z>yaZoXBIwh9lM z!68fdY7!z+VN_{|X@d(Ygf6+T= zp|rplVWKi*fHIWwbF}t;b}@AqO$QH%y~cZ*Wzn$H;vJZct_W0l?>Bpws9Y&sKeOG&~&fnZbQ|= zY{9c3Z5teI<31VfL zG?a05J9|A9Tid=5QyOkq*{UquD8A_yD@K^AFpJJsO|l|{-3DF##A&->nxu{9UNYFH z$$X1InC5Vc)V;)jsZuPfIR~5ikwRhjn|jW{sD5u^VY-4fBh2!?>5fDSM25FMjh22w zsIba}X^|y!Hv9TfB*HX^IM@xGH6LLDVd2keGhf!IXd+4n*19jOZ>X#Kg2#KC4*~B@ zQ^;yQs(!FwBO(kFQ@T)Qa)nkEw(jr|k=s>tH=#GNSf!(FCJ8-uvh`F845A#9V;P~+ zPp0$^4M@>nMJ!9#+$#5a6Qc`-GQe{h%u5hLkwo{EQH#3M>sbqCZrC#~+RbPO0a(q3 zN7&UinNC(3`!HCo-(sSQeIawz=VbaiB-HzBlTK2&#GKM_gX7^+CZq7@WY9gVy$&mT zS;Vs{=au`e(s7*C0(UgC_q2o^-QsmL``9w0(nhz{&bFBs&AxZvCi|rZOINIOCYj-V zOgK*-7BQ`S?!3}D(M*f?eU?Ko>L`}o1+Vv;5j?3PTFfGBFBao_JAk9Oa%NHatkS9? zeK3giXb;}G=vK)if>zFtYOFr$=?+m(h!7_};PdZ1T&`itzRz&EW|?bwX3-y5OT1L> zH|3h5J4uhkS{~vktS2FkhRsr-9RsjW5-~=#P2r2=d+}{f#Db7hM6Bg;VH}NXb3DWX z>_a1B5%vNi;$5haYlvJ}#CJOp@&A~J_#Y=C{vAZb&vAD9<%Y0v&iMC}2L6_OEHn}O z@TOvo6Z~AoSYJp)JYy7=5KGlsA?WA0yxphP3gI``22uV_g`0?FSc^i0Jjdzn<%pMv z>n-|2{@)aSPOQK<4#vYM&vASE3+*FzI_gC5)&cMu}s%I{Kj~c>q^*&C1PMHmv}Yy9}+Rpvyh0*w>J>| zxX;9e7>gs;V!WNW2)3n(*UR&$X+xg#1a=HGr4SKc0noJ=`zsZ4o`C+fM92jcy;LD> zlhglJpsNA*lZbdY#z@<)ZxIm>=MyN0;eU~TmqItO8T${3$bTWw-h%o}M7-ROn7#yK zS;VCX4`*+cYk2I-rClofI5`etUxECP5C1eG2I<|zZ^?bm^hebb{;1l9y$xeGMEIks z3jabPjMbDVf81)}Kbv@iJVTrED00Joi5!Eoe_K9p^k)+7Sd@gU8}=L38bJ8tr(vIf z`bfm0`P+!_UqzfK*IC)WgZiQTA0$qa&#C=p?6Xw5x zD0kxbQSQp0a~*aRmYaBoTn|k7QKaW$Eg10!YHcF?CzGC!`%Xk7RYHV6_xaktj&-`k zyHM`R|61ZzD0dJaC*F;6SN=B=zkzZm-h*;i{;P;pD0kuy)jr|X*mqC5 z8s$#B7v)Zb|C7WTlsj>aY`>V!=SfdPJ3?Hm+AsLON_x87t7ykfJxCh)&AK7?5IA6R#=iEf{qJ5`*`Jt- zGFX-@bKXZ??)hdR#iQ2+xcJQUC6@*n>eF?R`l8iE{p^7)oKOEysO#7`(1BdmzPEHN)foiLgNQZP1;^uzhcZ^so+fV$x1^&{8P^_fUI)_Q$0V&`E=g~OABaE8>E9)GwHAt#IdjdH)`VO%>uTHz{mh9=|y@@@X*p2zk;nNFYzb>o7 zSldse?X{lx_81?z_j)qQGs@|$Zyg-zr zG1__9Ri5jUB`<9`-Dlbtsq4vk_%RgM^PiqM!*-vp4A(+jtW&FT-G}QKF1pjWKEp*j zHA&c)IdI0Hvdku?X`qPLAMkdNk~=ev%o@K<-22MYg|q1|?S?sgNgecAKTY~!S0r3M zbY6~YFxCtvj!ZldS5fMTE02$|B2ca+tbi>0KBnnnq{TDc$Z-0wI?+3@$+6bRE;wLY z`wyP@+xFV9cF_?2Mz-_t1-O3~hu)U$Qs+Y9K5pb-1Rh2XMQ1RKV1~PBo$Mqloapny3$nUUcad~%s zZ<{SM#)q|+Thc|k9Ba7-ljZUda$*}f=D^U31D>Jfsljq^W~P*}?P9l4LVKXxRiHudkw42<;K+{RJ2F9thW znLh5pVjIHpq+>ey-KRUf2|I^~d+hX;bqub+p41d`dZIrSuLa79#}7Esc&rX zT;|Cc(y5CVdRcNdFi^EyneY zt!^<;E0y3c%E3Tf(4?bs*SEN5&7U#Dy}YH)U0b)PS}MiVtBTsaWQBXt((3DF*#*5t zI>ULY08MGsku#Y_pjzJ#p{~9Gp^b({H`489a^1?OuCA6T6?t!I9i_^{sJOBUDMu2Q z%9KdDYTi||OGBP5s3baYctv93STjUzlDTihh&7g9ib4x#$%2XqA|>T4wY+gcqz2mu zn`Kx1|InUg@eqnXay{fGK3s~91D4`><2w)cG?VqAiO=`-0`(m8sU(ZzMAAup=JlH7 zw^{h{!IvBv-fN<%f0v17cELr%$WV^-BS5~BvWR5q z;fHdO>oa+GLN3}KUFvH7>9wHjve#H5~5(9&9^mX(lKueL!mhAOpFS!`Vv9&^!l z%bm=MtZr`A<_Re^tq^7g6>rGL4}7Dit)?A z7(Z6@`wEXK`~=APqR$mNkv5jMi-=AunTY$5MnnVSA!6{sOB^rzZRTe(E~d9o;R5oJ zf3f!){$lSp($T8;4=Vl+Vgc+S5;JjzoTA@S^t(h4&fX(JANzU6mq^5wM1)?hStp&M zP|W+_H}`4KKU?7_g=Ij_gZYWPZ;HNM(PF*_{(Ns>_~#YwBO<>2ihh}hvU^q0oeIUg z5Ps`0cncL>qOeTi3?jF=Zmg|tt^Pahy+_)$(?6|a+9l`7IXo8xaa#<^ z#p6O#B4}h?xLsgq9rVz@IkrK0E%!Va)TN!4!y_*A;g$+Vxv!&4wPW18I95&6tigEQ z;`^R<+Q{4o zIo8#F`0c^P{3hYDj#Y1hz$2!BS|8tGb=l#k@jN_&i2$wT#^!nRFw7WqeT`M;Oc*b> z-k*bgwWIPTg^f2h?Ti&8dojNAJ8WZOJDc_-Rip+MRNHb>{XJd%XH*9^Rr~90Io1Br zsVh4+1*Em~P5#XKejQtjj5o8Y-wW{9yKnr#f3$1=2e!KIF6Qs%ow=U#E98jU`C`=L z{E9r!;Bt<3$T7IV6$3EZa&;hPO=`foW<$WSCbizaCf{=;U|WkZ7A4iMV!S6t>}r*v z;>0dkV=tQgpqrt7T@U;|F8Lilx;KaQGVVF0SflKoJ8$Z|^0~dq(cj>5u7reT)olsO z>KhW4)m1kn)HJjv@O^FW%7z-6Z!{^qw;>`di3XwBayVqVnrX*GcIu zznJC)Wx~1Kk4T>dCO)g%E)yO6i68tv#3Lo#5d7u$pRAtB6BNf)>Es+iI5+Zp&HQvx zzt%2wMEicjYf;egSw?po%mcp{DuZ14tX~WIDqJ_>BLABfzWSaB`)(+hIB_D)7hwq< zMp$4mTfBc)RaMtjFRZUxUSC_kB6N!*U()9{(a0PO7s>ZdXfVHwn%|L;7M2igIJ50_ zAw#@Z?1LAPPR6;`3LjMXq(a^!uFH6yh+^BP==};`CPEM22`Sg9@V`?Zc@SyVj^#vW z?IT%$Y?J%yBjdxXzNj z_?vp^_#J*OeI(y)%}$ekc$)i2%AHFe$#>t`kYyj4gp2tlTKmX$D96%~pwsbM`$)c{ zH3g+)9!VBAPMtlsuDQN?Y5fg#=P;j}Ga>Js=j0M&M1;XUlIPVrMkMVV{HDF_#XsHR zu%C1|FSHdOzin{w@j-+8H5Ip2G!@@*q3bUEb-Mq#2{SS7&$}FL-ksY|48HihU&ma8 znUJ=pPb6Plc|3WL?MRZ(yJtv`ZR9KSYjtnYicVq>D!xzru3hbFzC^y_tL7HDB-2=H|=>>q$CV- z^w`rL>F#fH^w`oI58y1RHSrTTKVaLCRAOA%zTL=vzB8sIq1%@5v+Z+z9bJhy4=2^u zcyg@W)3m=Uam1>{MoFDA%KdC0Irs>hNe+K8ay-M$eZ{W-+12#I5$CwLX zyJua`Qt#76_O}Ye*;Ms`B{*Hl@ryk;>E+JUHQSlOpY<5-Ovzl>D$)RV5}}0a5&K6 zZd}lT6G}31F3qGJJq_-RM&=H`44YTpu>zc*g($uetm1eqDt}bosKlS z&@gfwg2*=7m5BAP$d3yjR_R1Elw$k<9ncigT=VipzeB(50|Jl)j^iV_!5WZ{-?NcE z?etG;f7*r$!gnfuH!?iy3x8X`Id9Vnz@wuqowYyhO^)@2VTg2;i`M^51W)Ux-2J`8 zTMnMN|D)Ww^nb5XA0l9X$9yustmoGLk7FWR;jf)elePcb1_gZI)K1H>`c*FEh7Hvw59!h#&EWD{)PPO?9O)h7w`YTm3Lc@*MD12 zj#!)E^)>C``jr^;Wrd3=cVhARu-JWV`*ndwyR)6JDzrL#%9BNj2aGKL;;h?+J|UOw zt6L~7A07O_l{ppXd(HKy`Y-Wh-f8>@=l2!MZ$Gy$U$nM=S`2Nmhr93?1s&tP*!TTy zM&|iGr!PiWk#lZo_r+$&bGmq@m~ryicIQS%apB2l+WjKlKP=9^{HH}j4g>^cWOzN| z94nme#nlgUE3Wj+Et`i`A##4c@RTDd`{;@K;?nE`Bkz2sCu#KqrI`nkumVP&CU$K1 z^or@8vT~pJ#znfXVh$(zV!8(z1ACk!2PKf6)b@)%IRt5HBUWZLPs%#%`YHHNh%v-3Ta_$3E2@BBwm;vSUvM737w=wvPPa@(Zu;TLNUYtEgX#0r$ZSkFU!a-EO5%WhfI{AxyO^xM z15`?AaUR!dU5A%$Vya>f$o%PZ<3#GVZ7jXWl)7Cab+ditzVOsN>|v^5?eMnOKCnNn z>o(J=)AV}RKBQ$bE;^>^XWL@Lxp^_-OvhN%Pvhk3_P}D}5{CP5@jE^4pWy1qo*YVB zfp4^Ub9}G<>7tecF0t}vUC*#2`KvTTqP+h$pQH@s`}=xHKk^-C_aK}6?O7ZP?%cFY z(FVNxokS&jDsZ0qm3ik&o-2F{V9C*59JA59;>z&EZ+-29c+dC^#t3hxZEfsUW39&* z^MGsX_=mG0AG?0nH1F;`Js3xMK*kn#bP(3l$c}{d z+M0d*S{d&B#o3c@?3(VI>O0&O=erU0?o*WEFf^X?L}?mEO=ERa6;9o%UTVncAa@om zwYwKJH!gEG%7)b~n%8DyUZ5`MC3nOrVZE*a_KC4PLVmfsVXAm4&-20roExtejm;~? zDv3H+fnVP24#2!I?7(Y%&7-i4rp?U*z`jNE@Nz27U9I`ec`<RIu5e@_mP6Xng0sMEQ{}#Ba7EDY!__1@bvy7}93<#lI0SSY&e1#@IOa#9Xkw z=Q}>%>9ym#(GN5MB+dRnJJSDvi+O6p#qb=X(vJMsGyx?2riK0x^iOd;k3=y1UoHG0 zrXpteYzxh`blQ<$VxhT)QakeJfUd^m}idHn`^cA?)Bzd)=xlc z-1zXt5%3xx8L(iSrHK%Y4wn?nT#ggZO)D4#J);qG_d)Lb1~kV@EDBV+6%;C|g9VXB zb<(1;A}_{Pc?uv5p0w6AH=whK*3M0xjTwN(<;^v9MJs2cF|FcUKLzI_nEc8VUQw4t z@auC~ll}-*23*3L$xs_O#Cz(9vVToTA*D9F&iqWfB{mN^RZ28r! zRKdp*uB^JDb}706i}!qVoh6w3wEBzh@Svxud}NOiOtbpR4od2*&i+2hf#a zi1BdFwf~kh^uJGp{*Q>6_|C&KM}2(9;FZyC_3#;GdS@u)w>Z;1PtjasK>oD~8-Uc$?^veq1tRqA zCnBC#h|tS^i{aiULfU~_79UDg>(?n=pQ3uZOBO?)&ht%0$!B26Lb#RPa+1N(i9F?SV%;= znu+*uzfIBi5c6?=iAb;5Q#ua!7c|qoU*XF{r2kb#f8jA0%bAUT&;4zkNV9hOCyH8( zK@=*+LFA3^EEr}&57hg(j59_BP(WEa+$!%uO;>BH$exPrhZc|-Db!|8|Rq~o(@B~XCY^Hn&*cn^3bGtlslJk9@_o$BOt#Q z`Ci3xPQqm!=b4QHHji29c&+0+`51EvCIWi29GmFbORHNKH8wBfKu@1*0dmiM?@^(= zdBJfW&U2i^UWx{co+M!uLhjhPM2v{%`8s>>khmxJT;Lvb+E`fK=^cB)f$Q7iPQGJb zFrxq7e`vGi$7k8|S6uSmYR^>9v#CYLoyo_$#*B?UU@I8hiBXP<8EKVmzwEl81Cp~{of|LQm}JXy zj&vS+=a}Q9#}V8A0)sm*PVU*!-F|b*8^-#Q;|6vy?D)9-YXje~tv5Cr&cfpkzq|Ou zt}~862uK1n&dN#U^*^Y`$AGbHHFIu(NaNFGRd(Qmz%z(ewHwf#` z7F^QFZ-hi$2~Zoz|G8#^CTp9C4*tZCFa8c6{*Xr-=jU5K<2;3n@2vcG(2n&!O%p)U zBXIo*7n)!puig=H^s}hSRXC-(fiFFLZ>XxO;nsqxh5R5lf+F=TRm-piqQ0gYi!-rw zNsNUj6G5CNq7D1P?egDgY&Hk0otS7{-j zmSdY)+Q#*?Vrab2HZw0T-+QiO<4!jCmh&l_b{fO)z}TE0qrhH_W5q0ryPs`}(>Htf zqKe_3MdjBA_i(v=@!OjAjBLBqQ(az-J!RFwvC<`NBRtoZUkkr)nEXb1zFz)y_+1tB z8+p?x&z$l(@S7j>TXM%}&&=|fW%jj80=BiYgZ^6sV?5K!r$Kf`(2uE1M!Y;*GQZ*_PkwoRaBZ8vp6P$Do@2%ZF$Gg%x(gf+ z7x@nO>y0er@LM9+Lgpxzl#v=<@unxUd|25Z>h#JtnXinBw>=k?rw27l--{}`JVVRm z>N#^?*YpjB4TGoQ?aINmThQ{UB2QW~|QCvfeEV$JOEq6WE z$xl)Dth&~3H8wB7t~uzDj8SfJW*u9iAiG44l+MA3XLSp+i=kLiCisMQ&y;b90G0w# z;RGv~9LXRdwxsCNp`5 z5FTRWuqom4+Dz>ia3+`?dx2L-}x!$BV+ z3#J3AVu?90Dwkhj92$0kf>$cITETx)@O}lkz99YMgqQ&Sh7j=_QSR>(;=|z_pR%H# z5n`e*&iMd}b3WrRr|0`dcyZ3>T+G#o1B&xLn9vGd7kF`vbjJsH8zC4FTM4mH_z5B6 z;df4%Qu5__e&?XVpI4APF(GrRV7G$e91rY=6nI|z~g2NeDTh3{4PL4|XEPdfHjEXQF&l=Fzf z1&$t>OgC)q#fu1M z0A$5}^0J&}o8OV+RO^`k?5z=cH2x?g zMe{mEs*n?T>b)fD4mkj+&@W^br0Z9{fWg=o!Movi$W+K{7>;){1@7n$!~S`&Ym)>E z+x;v&rFa;AC7?F+U#k&7;&<8b@7wS$;9tX|^YfC;U(0mrVUJo!#BSadMP)b{TX_S8 zG{j^;JD1RbhR_nsoyV zD$B=WooX;YIG5c}JtSr|ZjUgGub}+oY1Inl`%MvX22gdzud-_WNv`Y@@@C0WZScYV_A)9|KNDmxaI#Lr6oq;ri@( zaMy8@?hyYhM*G=$U!*&mKAXH;&XvjgVmVn}ek;VSeKF@G@4`(Rovyvlu0o)zG!dYt zV>8r~(X-hv$enZcX9shcVH@v@cR6nEILDj}zL!x1nXjVe&W)Y*oohN*3tmD}X0};l zwjW6HNU1H!uV>HxS??g3(kk*WT>ZsPf9>E^%fmuWdn zO9O5QIyJiqL9c#V`wA(H%M9p(NukBvw+vB;gJi7(U-VY4p8154QP30VLH#;h zLK@OYpWidXx5blMl7`r2?vr-h??IhEvMXdXAN8mC9QV^_Ldm3J*10Ub;jZg-WK2}0 zN?9F&eA9R9{$$+3np85{659_fv5i)-{l2%VCTYPfy(4`c>U68D_y6dfhL6mP2TKky z?g9uMz25@-BOb1`w*WqdhkQB8&Klm$xGg!-jKCXBz#EUS7xU8&tqIhUh)BlJHH_K z6kGV;deMWS?h?awXLMe*KhyVjPi9Fb_~x167Hy=?J~G2ceS}j>&}yR{TgXXG6D?w( zWk;x%Elc`-t*oaf3Yb(r@p#XJ4vmW*hc(&oO@M<+*uo3*idL_67o~R-2umGXp z+!`h8Zot{PDmSix+OW2IT_ZV~L6B49ntN(m!&Is(GZ!vdzDUT&h9i=qrqxZAP#)Ic zuB};HgP@dOr6M)Tx`L@Y(<>%tdYr4eiCN5GjC@`(zY9A{zV28HPX86*iIDWa&4SaPXF;V={uZ3pE#Y-`IATF= z{GZVq5nmI{EooZ5;#EE{PSxxEW|BlI2qYx@Mo?U;Ncpp z+(OT3SB(u10%sm);3563Hh=3JoZ;JS{vE&>=c9NS{&}1KYc~8n8~(WsC!d&dwD-fE z@lCY60;cb^;dwUv5*xl4_#QlzhhuzSw)t1t@HIBP0r+ONA3%n`lQEfWnpcUy4$7C>EP|kHE#yLnT}~@@ zJV@5*LzP3ic>})qiK0XFRnP(sO6oKnS-DU>YSz?39Cv9&V`YG$D+BVlr%uS)+fBs# zBoCI~33=2-g!uT$%OG#sPl(0oO$y(waDE?@6MczrvXb{aU&)=gA(yG#+3q8-X5;!U zA`WXhh0g$_yr_@^^~!sYDKA;3+`mEy-g8jlHxYuag%Ii8O9=Yy%6}JOnz~B_>Ay=H z`415y|6`GdIJkQVr-C&=$n*)3&Q}Oip#Omobh{K3a-ivuzf?GR&-DM85b?V34KbcX zLQKBggz&#qLH5}!|4Id~B}6^=70z`k{R0ZtDoCADbRQ%y3S7&JHY@*jK&H2k5aktj ziy&Wzh@+f;BJ@BGmk{Ml!Z%D^WNt##V-_LksSAp9mlL8KtCT;-6p;@Fd0v(IAEXls z`4V!Y2)~`-5dH^*z<)xB#`P{C@)?0Kh>*Nt`twc_=8L>t=6?nu@-v?h`7BWQm4pb# zJ4nP`E6SZ?8uNEAA@a3V;SVU-rr<6G|7o7kzi_Xh9eLIU)h7(9M({-PC2CMkRkTUq zXzHis6Y*{qt065-2A&u^Xdc3xjxGzn43jO%#9c2O6SSd~&m{`tl?X%KQN!_J7Arc& zOY>*Y4aavXgP$cC;}g(XjrQ}y5oHK!Khm8I-)RO4e*~G0M?f^g)AF4XK=2El80fUs z&Ubnqe8+GmEOhL=r2xm-$z08zmv`2C1uK|w8{cV^?-OWa7`5bbNcG4y)6@W0P1S*K z?Qavd5x%QEaV5APNv-Mg%rqfUlrD5l$Q4`fAifO~NyFoScJHhGLB2vGxH#DL?T+Fl z$>7n%v@?aHfsDtFh!oOlj0-mO6!;SEi@z_n^_2Hpq1-HIf9G=NM_b1@KOWT()0*v# z6H-WR{|r2@(Asb<`Kv#{jMk7OoVh8UHlbI`)B%EJu^x!KnWyg zK$c5}d)WV8ugp)B>8|jrGE12wk8hXfVSjZ6!~Ft0p(M{V)7f4rO26#nmgN&lB3rY~ z3BJ+A(XA1Cpw(UI%0CFrULs{7ljIivV|+hDOyI9v!MGmkP4YbreeDC<K3CLvwkJWQ_Eab@WuZ#z=QuC#?0zbA zPu6bSppd$Io;rE!QvPn!6kOD)zK6`zl1xu3S}Hh2;vR@g&2iAPVr2Am&&(Ltvt-ej z?q+;JE>XfqPPigcOlepDyEpBPS2@TvXEklx?`^uXv)LnkzwS9bb*K4D-Vrf&pMHOM zch}*4aUP}n$46o3d)a3G5btFKIJ0jZ%Utck+j+j3cN|oA=Zg1I(PK<2?>44?xtk@w zy4%QH*)4PMVCbbJS9|AYxAd39vMv{?lB{o${S9e2jW^-MP}Gjo(IW&yMm$WVM2(pCyysI-j$r)S>igpv`WhUMFI?VhIiqmssL zP7!Z|wGk3+@#iSFPqpP(UvwA0w}_r=0*;KBo+!jvI66vb)sx?oybprpuOOUWf4ZCz z4h!#S5zoQ#q%iw?cU1+X*4DWjD;m}qi<)X6L6y4u9*M2Z`0s%xtt0uDh!o3}_pNy!Z3CC8z15nik+tPaQ{_Y>WN zxjE!DiCC2oqUJS;eM8L(vl3`FnQ$YOTV@nYF>;1PvJmm(5ozee7tshY!*GdbxN*~U ztq>EG6*v?6;bvB%E@n0$SWRWMaDe#xnsRj>nwiAq^=>S_pk;>qx5m0UcWvFe>u12p zeGyq}ng*WWA_*D83bL?*&~(G|=;Fw?pt6<*)Vjp=8`iC>S$F-Adb2u+;xN3bSPOqj zx`a4fPg-#L^9-Lf(m!ay>3^>UXZ%|&IQ^+N zR~i|fYaor&-yNPSD}M`4|CJV81r&gMH1fx2IL4DtHeK116utm31rPH@f6fWm4{N@f zA9nUhnh#eGJNp_Pp6L%5r*WG?SOf>&-(Y{K-=8GX-(@_g>>4M3i}Qbt{|t7frEyrp zW+-1TI_yWwaD2OGEEJ6QWgGss4eztzlneVZ+_20+ojHX5fAZz{N{P>e{~FkNrkuE) zPez$LZJ54Q-iLU==HFz)IZkRrdb|FA>l%pu&)DcWR%k>2qrjiS^Em9x??*QOXcTNc zo^<6uA>4N5dzl4%8=kEQ$MB^#|7&b`oeke)!?nJD=8^gPk3K5~5rjHwYgfM7i1&PX0OF+ZE)RFan(*$2Yn^uHZfeUk7A5?-Qcje^+<{>MU*^ z&bt!A-$RIe&LBiN@(7X70z%}EdK&1?IUV!4k`U=#ONjjW6<(!aK*3rCzX2F`p`7zE z{OiOof*c6p#o#*=f+X!N&STAk`QwdQ&=?b5rpt!pM!n+XKhd|!r1xpMWay1C}$je@%jwX#o$R(IJ|`6K822h4%(gp zJLxrD8|d`f!b*p(M#PUUMHtdq=afvF51N30cm=}T7i}1I%1%HU8oYX8XS_5nWMZ_m zihmtn8897&9^;r2zB1*xde1sC`&x-Xg;D|k^p1z=sJPb zxC!#XFIgOPe5n3GbnjqN7tRFyG~LV`t@qO{%o+7Zn&aQxaM`};?XOzUy= zk8n0N?d^|F{ z?TzV~=qnQZ=m{kg1kZHZkq;;C?RUn!&^x23VdAd6&-Ny!Z{GW>o@5d7%T19Vj5sIq zgpu~+y{?`SzU3n9k=}@$ef<$5f7+YVbSh(e_sKJ>u}PleY$s zh&_bO1))Dg6z>_jl9B&q|h<;r#>V}GSmC%GJGy;O7r&TdwCaM*&m&>`&7sSocZCcjJU`)#xEeShI z8KIRHT-PO`RVD~x0r*~`tlsbs2NdpS<{hEKv6$g_1(Z2rteF0YwOJP6Y&`7uxK_jP z7&hz+mZ~QKf#_cy_LXbB^}w%!AGVc+|LuU3d*NJ;^ux-q%vI+st#8euGTZ7bm1bj! zqa``4p7KpM3=tNw(pYt6Tiw;P9N9FA@bJvTyM*Y}`2IMKmJy`%pBS z(~hqP5&1*#*G8vnA73BE`v__xKuyP`q-xG*cSbI2PF}7UV9z|hJ}zIxpz-ySt}UTj zzaw+zTf8U2=pXBJq)uwd3B}CVU6As|Re{xJa=`iQs>wV16C5oqj(%5yqdy_By&&$5 z!y)8)e$2e$io+q7@moA)6aUh))^ub$UyeTUY{KGDw(*;gD+zj>a(-Cw>S2ibK(kV) zYm$i+vs~CUi_e&F$T;zwbK5O%-STj!kuu$k5#vgfxutVD_Nq9>@J0v24J}P4o{P92 zCpc=eLQiFyABu71Q~W!VKJE?i+@5(K?zWhWQGMp5qkFd(L>!`q=%gc+6X%9<4&JpW zp(pah^RAqhKi%G15c9hfu^WB#cEg?19C~V^`Df@Bxi$D{@0f(>t_iNfPM3G|&mH$T zb~6WZA8YivI$W@HLoQxUPFCOK=)YZ?>{@+8d_Rnz!(eNTq`L3)t_ui}P<0(f@ zRw&1PN5RP+!~IEb9<;ExbRJyGa;CK``}kDDk+lyNoO58!M2C0B-btpnnLg=e-cyn0 z-+Gfe7d9K1UoAU%OE9=NztcB4A|vLIv#CPN$Sgh>^DztSTo@d1b9bKCS=fZqLJmTP z&+9q|dcjt9Ue*~iJ^qkOoWAjbq8jr$Z!qsEQvFT5mr!qV=cvwGuD8Z!OpEx#GZvSu z&Ip|KbX<>_jC+6%d9cv%{*INME$Va()AII>bQbo-I=#4KMWz?*3UuOxNWVYQnBuNU z5+?wrRK(;yTJQ;K3^M*AS3Dt+fU_@=I7?F0ZA>fbW<9-nEFycPdFjXg6iAYsaK=EF zi?i@VMC|@WF$X#pMZHqyIZy4*K7TCY`gEMhNs4s!FNw~?SqPWV(eCm@JRWR%=>7iVIahj;7am6jKr zqS?Z7#)y64D-vs_2sOZ}z65FT>J77|un`#}jWxckv{yV|PMIvY?jV z6!L{TYQBj(YQ~zBT&TZ=QVn&tBncWRU(oSUTU~@X@{PxkyU24KTk=1M@^lKBjZQIZ zPB-P5A|oYoi|jojw?~^R_wPo|o%KH|!TZ|qLzGDFN%!`GPMmX!+^+S#H>^GXv*yp{ zo58?BXa!#`(r(^+>!SR=b8o3^a$Gn$BkB!ri?{DX=VKq;u`IvuznfpiO*#1=oad=* z`A*4qaHeBR_*4*5TQBpy6%q%|z67T$Bfqb`xw0kygPTWxv*b2Vf7436;f^C{CGkPg zAAML8g;PY4cSBoF#5IAu3nRBi^yfKRAm4FEv!uuuxiix9`@Y|Nw9awi@A{3{k`vBY zBW0!KmVsBgSE@F?vo5kfH6jLD|1+w*fee3TU0oH=6{!P4JJmvocwl(84#?RJj7q+~(( zP01Am>us`UcF7#Xw*c`;xg}TcvOY(ARc}wNW7;`Am$j^Fxw~Lg&uql8d30t;MmP?c zN{X3p8fi@By?5VOGv0g%dXp|=46&8H)9$?87=OYM;XCo44J?V_-PXIehMJWkx4m#I zF=e^`u?pln%aQX9{J-8ikSi}vWF;Y2ywO1FKl&AXmz~_afhif@7@T2Sb~3KMvLzZ+ zN#VTz@LjBk&e{1c=jPMJS0eXwZ-yOgIkC_6SHNgY2qxiq4R-F)-H0dHwX4HrMzoK> zO-D>69wq*fC%zz!8QWlS5Ey1iv&r;ZhdFP zK)Pud@t^td7KhBoJLs2wjXYGUJX~<>)Z&pC1JIt)hhE&BFGuB?w?j=hf!Wk1HC^$Z z1gY(cXBb;~OM;*SYftn;Yg%q>*_Xlj;pVwLw9xzy zF7dn^GQ@Z$&q&FB_QN%^abrVX)Ne7;+!A~Z1FSqtF0zQRZXl1BAb&>s0@2eS{ipNz zgv_D$GIbA0{s;9QTP_btI_hu~=Az#Y*J0mcm-$MEk(P)aeVPgBEYWjA zK)r9ut)t-*E7|~cr=eZQn!6uZrKcwL5r2ShK5BCQhj%wmQ?fx1g0pd9=O|C?BT^2C zeX{G;M}3Juo?5f)Ym;d z(U%aBFug*(#iKQRtAQ521NM1Q=<)8x={EU}i;k>sxdl4T=B|$FPj$W?%5Tov9o3(k zm>h`7L7z3TVbQ(jqhJlMGC%5>(DEpxq8#4Gsv4T|FPsoH;nmlVC3=IkJU7T3NeNBX zdHx4?d%jk3W3g@_&~n$}Xl)9A$ujM^orbpnBSJ(<)*iRHZ?Q22W1VPmZ>*UtdXe_t zHBCGF^QpY3|B+_T{?#q9kMPUO_`9E_ie{=uYwimfTV&~$9Y1e8Y%wS!P7*tMj49_F z$!QwX*Ee!Q_om~qPTGP!mzyIW2~J{IBfX|)mg$(X(vv0Lq0HCEo%em}$a*Ve+!BB; zyBF}SxZd0u7=sye>?2zj=Y8*n&e%Q3cZ%CI?(0}wh(6*|PhrW$;+-*88Ov$%75VQ4 zmz-Sq?=n|;;aufdaus;u!`cZ?ux?qiFCI(0LbhXmYr$H1@>$k(14e^_dPi%js9BFX z?K-OWP-sDx$*(SEV{Zd``1ou`>qJ5GzQylny~ebho~-t@EzI?Up@VpDKgDgY3B`pN zSAQIOw(MJQW6vu4->luT_VK1gZB6OD7~jcG^_~0_@Cx8t@cah$#{jwaaTNBy0dkx- zKG@W3Ot}gA3}>}x-QO;H#Uk``#q~uc%lc-<63_Hwb)1=fVabKk z|GUhuo?Y-(6<>ED^cCiJuW7n^vcub&AJH;-h9GHSC4KrN&kIAAj6D>RHWPN zSp183_k|MN@zY24>Q((buQP9(INtdrHk@^H3-$iK#eEUy)-@On*$wzTU~m z#f90)bL6Sdb4!woNwL|>cEMH|_1_P^JIq`ak2OlhVlo6cq;HvcHkjAJK@8*oy)x7FA;a% z*})#9r@7vTueMdTkBYT&go-lX4jmNIq_>*>nma{}AFU}D8V<*QG_E14)z@!0^Dc>P z#rG7$ae3>a@jY*cw%m>9q3{3YD|g7&%#z~17l&@!S4ka-^AN(wU$hi=L)~!XHH_~& zFcZIL(S^Uu*l1+rb?>R&v;Ra*{s+IyUV;mjWG_$}ZcmkKF?VtpttV<$*UEk}sI9Tv&j0ML4>5;uEIZj$4+&j|qqW4$^UW@P z`Iu{uZlix&a}nEp^mlv5pKux|o8xHjiCQCLK@W2@4`Z0i`_{3jCo7T9s~63B1!EdU z41Q<%AN)8QGZKT}TJm3$;;elabO@-o#2m|-l{N7~=gifYpdWLj7_Dw|I!?!@I`=KM zj(^p?zg{zfd2$3ezT6OdBxVQRlUVoQ(9fG=-K^UzGrr@g_apA)osq@?_3DkE;$6Ri zhkLIH;Ac$a*v^e)$>)V;mFgPkVXUtXLMI@EJ8^e;T2}T-L+}CJOCVzCcH?j=gbaC` zp4=s%LxYefTq|V@wRB=yl~q8|SjsDIDj|Sqy%2}OiaHpM8Y2kh7y+ok#T`D6iw$v# zoHl~GRv!%3!9ZM9w{9xg(}GA4XiqKE$aBj$!kjWFp9r}QXO!J*ARHh(M4}AOj9<5* zw$@n4I4yZZ5adIUDE*Jt62P~nfmtbBcBy-9!}UCKT#d^S8pPE)t5~s(^%d(Ha3Z>~ zTB(i{4%AfZmS>r@_DGQzT?|Bwpd0F0HBzK=VdWa$IxU4dmnxyo<*c+t_4UxfImEA! ztozz^ zGk~nELyJ>K#Bu+UQHXXT>U>C8Y(>R9#bFh2$#NR5#A3s;>+3y!++Vjj|yPYM$0l2>MH_sxP>h zQcF~41Q9DCAM8e>w0c~GH!_1V#;`C})jowbRD_$MUeM6G9%wHEO`tGPUAd-cgFMNp z>P|}QRBae6kTXPLXbBo(IX+<_nuFG@Yo6bMa6`Mss|pTr*ACdELIW41$_aOs40Tkm z(w>ZbDZ2F~LeU4qd+##+n=ClfPvWMzFw%db1*iYx7M$rFwBYnVoFD?@Plk`-hJi3Lzq#0N z(m2DfwBQV{^diAV-vPrtM!i=-9vk-<$w#1loWgl_kbDL1H_*QpkbDJA|8>~O1JL+A zuvg;Yo+0TU2K*YHF$&)Y$h9U!PlW%k0e9lj{(pp>b8DS`KkS@e>pf5xif|OT4u39i z&KTI7qVLlzX&+z5v&sWTg?}-hsu3H{0#2JaF5duWIgOF6kbnHWw1RcbX8mN zZ^QouIF#aH_%`4p@#HD|G1wR5xmV#Y!u|(5sS1As_EUH=6@CJCZJ6GtHar$Ww_y#H$dcwoM>?R#wg|n?yR|%C+g@fD>+#vlS?N&X5#yvW5iA z$sL+v&MYxyPy)XVn8piy`5+nK)2YeOLKOqlS`^qK9jvEB7AH-mQdMgkk?_FGhxfLH zMa9EH=|Y3OKpXTnj;^A+a8zhHs zi6wk9oT&f7N>9qmg&zCznyQ)`*4D`hrpkSI4$IoR0_WG(RxeemvBK(FFqgHSIa zne7T0`*p#3Tmg8U_2rbGel842@fzsdy0N-kWd=*`(_bggWC!a%9scGVOZJAF5Q`j& z`8XGY)|?JMfezN!QA?H})X9exw0^1Px|;IE)s5vPWrNhZ3@7}I*f1&?m z5!^8zP+qv05R(R;zoGo}9fUs269|_;uAC48Ta?wLJTd3glrQJ_LU@D_lPKC5emo)Q zc{Y!*h!7J!&b3Lif)Mm86@IOPeg(z7c5|R_33yx<%13xPbg2^}zTXm}+(Nz?_(|eO z_wR(uF?K`(V$xJf2>%s?kXvt3cncxwWj7(}rGxMa%oPa{@0)~+P(PURvA$9XQ9ph{ z#CIJb!Z#5j{H=tj$9t9kc7=B+{E&iwBn16?gk`87tOXd(Bt*QIE4)_WTzjy-ZX!f| zH7oo!1zQxnOZjh6_`M2lRqz1?+Z5cTV7r3*04YEJTSDaH5aDHbuY@M#?*W;QK0@T< zq{5>xmteTbgb<=K2@$@G5aCx6B7A@lhbOt#VLXk5h^I;6-=;t6^QVNUpFTpw^D*IK z$geBNwGhLPB}DjSg=YgY{MCdAe-9zTZzV+d?PeBT( z#a)g0CE+zFC*ifwV@8PhO+tj@J$P|A=(vKg6zzl%@AoD`cB3g@3Lfh0qw@MTqz&0LvTs6s4FH!jaCb`ctgQc6tuNS)Cq7*@x{6WpZ1V* z6}MU9Vo=i3WZ)q^h8tl{N0$X(hCx>@4Cxl?Ou>bIe9&bHh+$Ef7si5Lp%YVn^uVhX zbc~ngzra8kEv@2T$5#f-65Mcbp=vSO&kr}0A*j7bhtE80G##PN8$EMDmyfXnpTE%g z%_5;_L(Ww+PDCGSD=)|dA4b<5@uI1gOaRyER(!Rgp?nqC%u?Oa8Sj|Oo|P-bKHX=Q z`)o)4VZw5syq7bp>+X)^rMQzVB_MX)0_F?>GXmFix&z$v@oscvjOdYe!#%1aOPm2n z_Z#Vd?WsHI2!15==qx+g93-{%kuf^F-t}+yGU2?ggeBfUnt4rUx`>&y()QGQdHKK& z(8V2&IS;Zb442fExWujYqO9@L?hyM@B3!^NcB@oQyMbBVZ4u@k+w6v~jLv3|Q(HYj|;Z?gj&MhLvmMoYH zP=1MhSD6e>ILmEYx&9SYP#_}`R{CPfaWi^QQrmo_BYUs%sv2r!X{>0hX|TAe^sMg6 z33pj+P$gv+>ekiPtgE)MGL0 z5&jBXKQBuVt~@L_8|&*fO5F!MSAtt#^Hxgq0fvK6$-^l)g=T@7DBfgsmC#gF-5bw8%Bi=SZ(mhHXbRC4}OS!=~H|E*I zkD9u6HJ2zogl)Wb)G{v zoo)&2$Xk$ZG^9J5xrrZiWf5{N!dJ)q5pw>g%L=Q}0ptmt7;tSxGaf{@1YJL->|vwn zX6EGPDCrCV&UEH8XYRZ?lK#wdliwtWg>q>paFMJ+~kQiN43YcCJ7lK zBW08)zCBLZAw?@@08wW8W3VfE=h*Fz>?AW^9sJl6@kOTM9{`8b@nJ zjnSIz)AN$7QYWN;jrCck^Il_S%z<;w>8l}mT5n9vC^hcMC?(yR)#s#4D~)S+Cn;CIBf6$g7#SA2M07F#?~)xA5wJ5FM9?6WaB7h~I`hE4Y}mhr+sq`AOcBW@?j z^B3=*=v(iZSTa$Rnf^Q}B^u@kFJky3{>qy8&OHUj8`TwFVf)i7X%$C$aqgnJU(88UP!4pHq7IU} zzR@uuT%z&5?Vj-^&<&~N3eWTH@Qf=N7shu69`KBYX2{6a%7Cl&Xu#Q8SrgIfMT;02 zmK{s=5H^j($z@nhx5lI_4$U~OO1NYSL!_$SQs`|PLTsCVcfhB`N zJjP5Y(4LtlevJVrRGV2_cm2#Db<%J|6Mybi8)|AH=Oo51NEQWaD#h&ramMnE>na5= z*|-J*CAc+Ve%c22+M0C&R96UCi92-RibMgvY<$hr2<14qUcK5g-$S-FqFoz=cDU=8 zRNp|+A2I!KL&Br7TC2{3r?9ST^vv)Gg*xjR8$9!`@gQEL%O5SCFW+nwlw4X=zT)zQ zg^P@|4TdODLngv!iX!oTSYCL*5gD>DLZC?%i_R4nCXtpIB5*EUr;r7mI3%MV$;(q3qdW(>4tH{ev9*!z68<|9H+M zCMX+txo5SWp@`{>oFrLhUSIsm=XAR6*si6K>!54Vo;6Nun+0c|&~3qKJ!HY@@5lHi zja)}rb=T4V9gDxFB;-0quao$lQIjw(S~Egc{bc_!`a_yL;6DC58=s!o#naO=D)^j zqAs{C%757N>bbeL4cmFSvuzu_^K$28=~V?6GUZjP)DrD_T4mp3ClDPWb^z_}YN?_< z#HXs27XDjd6YEjqOG!tz9{job>R6JoMI zN8tquzf|EX3Gq>`Cd8U4NQi}5lY%XTSR;uwlUuEsQq&p<_&f9mWc%h?iTV*3kC039 zs=YmY*b9_<5g`^8rG!X_GDL*z>!@46uV58nywsUU_gdn3g37;9!6pT7Qm|RU+Z3d( z0*1d!!7U2jtKe1zA5gFzkmcP=h&ARxLgbgSN7OCEK9~7;Rlz^fJq3GvgwvI7DwID4 zX)+$3qu|{F?28#r=$3+A=$1nHC_}{j-H3;yWk6b4C&5hJ^Uo-4kEK?N@A>Md6V$i*Tamq{&c!_o)_uP<{N(i zbRBs3O|zUVFUxQL#;Ny*^Ga=Wy7q6JW9V=^FVU`~p7gWQ!!kEZf8=N8c{Oq&V%d)) z&+CF?p~7Z!qn*?LNPBl5pjH;-O6wFU<+eHgh^Bluj&h zyC*CmeSdE$?z@y{)U*6C`^S~`i9I^-$U4UsCkaj%=~f3k`+2to?E!y4?8zCKfxy@U z%TC_E-XZ9IjdRA#aGsxG-VxLvIu!(@xdYF4@oXmovj-2`>vMRLx|W?x61$}? z)7=Ssz2r_(H{FdsYUy~qW8<=kO?U0zi1U}Rqnk=LhRfL$;JcAI$Q7rMe~;7byb&V4 zCkX11qt}+yoosHb4Tm`1Yotzsj*ok+jU}08N`7pHxvUf? zOx4X4^hr^-e7xi>5k9Q>s6DbpNZzEwTU4Cni5KY?lw{)zU^y3}R2Pn(i`#9;*OYhk z-h|Z8X&)=fvK3kgnmuD5F*35d<*g$OC0iCwJc?UV(oIJz%9drcj@@$z+ImP~q>p%W zM#-<*BKg5+OR1#G6W>KsV1b|5P5y#jck!=#>rUc2^(p6<;+w;n zU?av#`3t3A;1?lR^Evu%n9NH~PWg9P&XnHKOa4=RS7;7GxBGNJwxQ#A*ls?;qu1G= z;ydHs0@uw?!CnbijHdz53E(_qdv`~)Ioe}PX@MpO*_tNd{BlftwD{s2Ge>ln`MN!2 zC1v6AEh~;LYPxY0+t7DTebV)J7rw>4f5+X;oh|!Ie82ZBDp?e!)m(Aof}`ECX5a2z z=!@9>tbJF^Zen+A%BqWHfEs|AQLO{>3GWMSs>-(N@Efv_Y$a{IaQE=xB|R zvACP3d?)N*_`yhn6h{Qz&Kt)(F~2m)J38c;FmJ!(!ZCfPoS~lCmVO<2vz~CI#E8DN za`kPYbbnP&dm{`DXC%375F%T+xRbK&l+O(C~?Qz+ei^{ValE7kXt zWS(a_JeBVd8lLiZ^170i9I27#mfLC^UL$R1{bVn4SH_a-(&>^PLCMoC<@|Gn;fB-+ z433lD0M8+~ciOlLo=?wvO+`)2#yJp>Wb%OtFK=vL4>)n-&P0|4* z5E#FK6k>`BZuSg!&k#qJd3sX$%uj0o z8Q4eb>fAVxS+fpjH$@Q0CRbI{mC)|a!2F!x*|TS7S{_vvY&&2d0=o5i z$24{^u&V%kZFOUy4kh(qBVvX}#_O5SD!3UtFDykSOOdHA$r(~QwIVB_*WKrb;MiSc`m1KOmy)9{R48|)O*cZ?3=X#to?Ez!G+vXsg zdA5>s!vW(kJV5RZJ2>Q;1mAWp9!-DH;(syh&)`W#-${Rl?|@wz8UH&Lob#_g11CRT z)4#75JSsoA;cUzJs6Sd78Q)Ar@uDD z$=lP0IOhl25WmWX5A1cxHSPwR|2J*;JvMxs4R5pIkK6F4Y&g$$YQy~5@2)vv^S7Vv zj0=B@GXHKH&NG(UFn$v_&p)=KUdjKt#^%4yhTmwzd4@(C#&@Q(o4jj48`8gK!-H@; z56zI@0Q19hq_cqY8zN4*@_82geBcX#7b|~5NuKErypn=#7+Go>>MO9pEic9qgTiUM zdOddNKA*#eQP)s@qZj})vB%!fh`>Qahb9CxVlHBdmC}cQM0~OT` zIy&otKbaj!Ke9^2i8C>^8|tiQeybbs4oEC+Ix1hav7CYnMnz*?jm)Rob{oj2+E`Ru zjQ~6?DiRPfBcj!axkQ6?3sGz{ik#YRbhm^Q^PnL+ilP*p=!rRvt~`iVHdNaxokFGR z<%?LYRgA0cD`i;KcGx^bHp6ujPDoVua&>G^cw4x@;f+VJRXRAZRO(T#wnoF0_Is7I z1ZbE*y>#`BudS?r#u5EZs4rc202_w&6xpyhcp+np{)7Dy@9iE(I76PFC!Vj|mk?f{ z-)@ocAJ}rQ}Gl(Q_AZFjzSs}_5s&$;tl9LHwna|$8qPl>0uyi*Qd3AttP^5MHA0&p|kjfyB9Y8JCZ_62^?Ug_u_n;{ACDk*>He z2lV;G3m`8{h!Y3-2s$jZ;GZZud zS+AEXcpV|ibB}`C2~nC(BV2}amV{;a zJ_*r&-XuhNelwa(7a__YLzskmCggi1M0v*&UMAN!q$>u_eEJDZ z$XXC0UyX!__eMhGhwB~E|I>SF|H8fb7UWqQG&^DJ`)oyH(FWKi;mhKY4zGX6KHHO) zxZo{l3GrzPdVF5OkZzi?6X znjq*#ORM8T?4|HYt2I667U9h}K zcsuxD+B&IzEQC2x`WklVNo2;goREFs*RkLo#ozqc9sGydvlyK&hRs3WH0jRfo8AJt4m|vZSj!7yjDlbnV~t zZSc5C69H4YS@@>E)iJ`Hgp&=f zcBeRR@_DD@f=P#xd~V*_5K$I#P1sUUi2qM}5|%i;aoE313p#&1P4)rzVVAJN+vIjf ziE|%@djw9;a_8i;UQ6+C&LtA*7^x$n&pidHAuX}9dGllLnHRj3>`O6m=UB$-{f=2l z(?0DPD|S-G_!dD2@>sF&#hn!gcF9H*JHpZONbY5PzeBEdi>UArQ!f;H2;rTEFEyc!Qv2sMNm$8>~$80d) zg!$t=U06!U`@IO!`SIOy{^}=0p{fX-YW)lPt-yKiv7PW7bzTx35Z^h&y|3u|2xBl` zR(ObzmGsZbi2V!av!5fo+OS>I*vG1F)J+rIIn877NQYt%na^gylm6OhyM3&h1rNR( zZ8TjL9B9v09;BP4iIgAx?ep1HaOAh94QXiX^V#+A7;fw<1Fa6jaGR`%#m^5rsv-y= z4C&5h>?41o8BaVyF`ukImft>~%|qmDd)nx1*vGzNL=esdh&A0HUKOUaXBzu*a%Y|O z*~@fh-Xe#V2&FP(x*S_LuDBp$>QJXA-DU(%tZ}B>)aeZ5bSBryeRg?5&#z8OO4$p} ze<{lrWhS^s;Eu0TpS+H^njUL$pZcT+Iv&a%n`O3$8##X(TGu?M?p555@Ca;IcELJOBJOjv7Mg~T#fhZE&8BHBOzAIT9?*xo&=Qx7G;i;~eNiG`^5kmtHn;!5P*D~n zp>V=5X@|3Q(-ft>v~Md~2MTgQwP zmTu49sQV+3axfpR2ee)dSNOD};dcA6VmZLLaBnIk$l5w)bT^0ff;4+-OgZxyTM`hp zxsdOUV&fiZBrj`;P@rv33*+WuCDq6Sc=IKX~9@9iu9PSTdx?H{qxXD6k zpLfS7x*=Qe7(>K3*teuA39A@*Mr^vAFKlPq{5NK-91!>3zt`UfmH{c9~a{U5d9^zX3X^gm+3 z>Hm%er+>(T0}UIlDM>$YmOz##pchQ4JU3Zz#<#_Wha&{DjQ#`0CG_bKXMZbabpyU< zUITNrIbepHhYk30T!<6<-P(=)`&5kp63@iLv2{8g&bx{LwV^*)WX2*qoNv*;98eqj zUx(*8JRFDVe>33Acvx=YlnML;o;eEd1k{G%pV0^)@z?N-!uv@EWcYqSZRj5bziD`w zPx_w+yEgRC2ENwf&ofTi(ElsIJMrYg&hT9GYD53qfm0?!r~f^hKik@W<7oyh!#{8H zf6a!!Yr~!4wj#^x27WUho!%VfPka=at>Mj5HKV4_^_Q(` zP`Q>{ceXq$wJQU0Vh561ZwAP4yGKQ>tOAiExlbu~8;7hc{)d}z!>falIl#pP!P;uk z-|#FO+c?kqr4zd4_fN?0lTfTn0Qp_>ETPzU1ALPB`EtDxHwAqtadal^>$$#QpH6r& z9{N+3hWk032gglQX9!_$R{lRAyg>Hl49D+?;f??jf1fx8H}=)U6YyOy-{S}|!JSN) z1|AY2K4#vlOaCI}zeM?y_e_8G;SreVinD&$f1zv&@kRxk2vG^&0ObB7`*fz8jAt_P z|0dx~*>5u(*BTLshxJK(EFmlLf4a`9uFaH7F9XsMYuDnCmO)Xz>deKLUO}}1m1~U5 zg_keQtY~bkuUWOBvAO|?o}Iz#Lysl4a6|z1f%l@E+Hg#wv9Gn3U{O$vfbsBSc+w5G z)_Tbj7f1vxA)0}p$5KKV(&@D5pzWx35k{}INQW((uwmMK3Ki7JjYY)lFSXI}T>=NL zXY!TDy%?n2u(KRdcyu{@urpq!PcsAY4Ywv+0YB1dbFnUva?pNNz~L3N(w)tktPz2> z;7LG0e5xXUY+o#cH7V|W73;#oPp3P|M)x?%+Xy#pG+nrdwdB zr~6%xHY2p0ucw%af}5CFB3(xKMnF1#%yGAocOc13fG!$G{$e2?FYi`!cr${AI}Ix% zW{!2MjowAz`yPQOs|zYcmp;_NlNye8nb(Y_uL)V}X1K{U1XmSNA_o$mf!I?R`vJzw z_>;P}bl%>1YiIW{BR3%iVS%s3N4iys2tX@}NR|~BNW&~*gRZjn3CXoaE&J&ojS zvt-$d@}-xpSW&)w!>Wc#42X~-qZA=$M1pw3x?#z$SclJQ*Z^V%7>>4V!z!qO50o#j zfi59S+}5v0v5-Z&)>)pFAuK!xiH6C~G@Mx#p>-BHtY}p@fG8cO>sqL8$fQz`s(95b zP|g3w%JmQR>@7jvQ^&%Ugc$h0LO4dQ_o$QNF5sL8Z6U-UbT1(~imeKNK*2Ub3{<-m z-majSHzNM$fph-&TSDN62$9|&3Gu=4J7zk4gh*!`>~Se-UJ2X-_sMA3$dd4P6SBkl zUpC*GfpTf1dl374i?TWgLBx3q$w|j=9@AZc>$!m65*NILA7KU_(p%}Qq}rYZ8rt=I zi}8IKxHk0TQ>dVxavX$XswM)|<*?7UnlZ`Zcg}MBqxsf5i0^FXTOTts7NgNBxS^~; z?L|6k->K;cbs0!I0|?g-?0?YYMLC#X`+SRc4Xo0Uz+YSK^Q|o?^V}N zgZsK?;(=#l1NdzBe;Zk`miZRG$Dn5Ad*l4feN$?#!Hg*jE$2}MCb6)4{ zZ(P3fBd>Gk$M+N#UT1g@9y7e;3t#_k?CQ-wx&Ddz57#Z2|IxCC?+Qfj*z?Aw^S^$1 z;$=Lmd8>)p%%Yb&Tz!`~cO@@6@uv-UB*))#{JqhO;uN1r`_?h% zFCtqvt;HGNj;Pk>)n(%6N&h68So~?3iUsV)Q z9l3peQ9*Uo_VGp0J8rEuJl>+`s$+Keik#QQ?kFrOyl#wH(fg8lz4?&&s5#M`ZSL;n z%e>&&C(EKuGhn1SJTCJ~p_mJCTWrV2MoNi!eEAK_jz1U2xuZ8=T;S}xBqrv-zW%(C znLT-FFZ8<|(?5&+FzPc$|HJ+6h$){%eBd_Y3&#|W=#O?dJTVu2D-0{JJ|K` zAG(fR^X!%L`bYI&wd>YP?s@Gi6ZdT09ev1g&8E>$Z=RL<+|3DBG=BN%`oDMnvH3?) zhj%pg?|9~!njP^&W>Mv{i*{W#vgfc@!daq?Xt>WMO{B_+Stu;KbxADG9mNxwKJBE8IiYqMMGTm z6LG6=$o%EAw``tKf6qhj9r%Ioy7BG7JAKdYysY*Y=e>7NPioY**Ei2jJQ-|Toiy&5 zUFXHr&YisEtHo2hp6tkdEMelj(%pwHUG}R7uKBPoGw|12ztdP(`Eb+Nrk8GuiTK4` zpPhPo%Zb{uU7zgy^yv?p*1w1<_(Epcx^F`KFmjHZClP_ue}x5S-~D7bP}m|U^cgw! z_tMDt{NYYi$st&9O-cBV=GbgMoMT(fndi`Yq>-V{MlOMUIkV3)bB@Zn{S|m>;Yi#I z`!ld}zCxU1Vhzf}IwP*Qu0CUV@j`UslA)*U@|1%1xvpj%&T=TPKt)49)GOyie?l~z zQwg3G;MItqIO{P2V|^7N=*WwrEWp1he<8y?78&`U&T;C*-NpY;_(^TZyEgi5+2=Qu zNiGHv_Y6=qr=8!tYKe<+l9t9kzd0Qp-zCH7`3>o;QPPhO=PiWV?-1$epo}iZV&HUU zyfklO(lOk;r3`+S;Ksn2P7y5Z=Lc$?w~#JJl8ApD2cgazJ>1BUAC8L^OmHpDBQE)6}!;J zN6lGozZ~Zdj>nEGOt9Jyu*q3!xtt!P`4i!=thTAN{=#nnRqE#E0 zPmGxUhrN~S&v~OQz<4S*=6|qo^uzuyl{i|zQ`bENNSIvbh1;nv)`186!23GGMaoUp+CqG4&_&g@j$y?v#}HcE&lkG=7iPJ`%ZSc4;*A zD=){cc$LE~wKd1@nN^yfGFDJ$h4p}BLJ!E}_3n}ssZruS#+72;gxttnG()R~)I$@w z-Qk^PN{t>~pUZS?S$6Vg^`oFY#^sedb#O@G%}J$Rb5e<{S6QRWdLwr%JK0_z4LvOo zn=f{>juZNAn9@QyC*VthnTp4Q=da*rQHGP|QaoS6b1k0Dc-G*#9nXJ*<_Ca}<9P$m zf8lu=Zam8y({<{TkNzI*J8$EgfrXt>zFWp`D{vi(_~>}f!JOpr*j;yjF48@K!!u*L z3{TRMRqOxc_pIkTOe`6x-l2T^ZGkwU7bwnG?1?KG(3}yg^iSZzvqAg%%&!M|VBf{E z&?I$5FF6|Uffu;@??(d%$Gd!63+_E&xE+ugaj3i;L|%f>$D9PcK#{vyH;_cx@7fyE z8M$rN{)s}{5nZW;XMCx1kK{1M>`yN3?@eAxpM!fdZgOO8Er@vYoYHY6y}jc~Hh9MQ z98<;>JMK=Nr`zlpwAnGD%@*K_&dl`;*)CdZmiegoZs_vs-kB&v2=%!D@De;UivT}? z+alPngq`KP2JmyZML=K0)$7NvFMe0cRKzT43nUBvr{Ue{Pohkzs9Bfql*e$756W+o z@zPNIQb}Iw+vX+PLtkGn_%lMY1FqVppgZoCr+#QfC4?~bb=yWgj@F4g9;ga|DxHZ) z)dx3ArOTP@q%t)NG*hrZ4XR(Z#s}F?>XDFoBWxZ}PGJ$ZI4xUsP<#;AXn=kR1hqyc z%E3F_D{#D#BBujd9*7C=>MBFd8e|o(we_h6kk3K~|D!B}fIN^Kc9A&JALLWjnn zw6t;wOCPOe4(rM-mr@KmNja2Qq$F8pGI|w>bpK+esIsA`f2&N18*Y>-kwb$f!?z79 z`99L9MyxQ-QAzJsI7ct?KU47Zft2wvymgLC`lJZ_2_yY;EjaxbSa62tTud67zcvd_ z|AQ8s;Rp7@Wc({Iwo4cQ29{=5r=dYNXx&Na#_z%K$`rEv1ov?2Y6HXI*?@erPL_%Zw# z*nf%VNrh*?t_{O4vf-FwV^-tJZwh$rJd0^(_E9X&;!jiNkG zBi->~|C{o^i*TCUx1nzA?-9oW`cXo3AWsuwaCk*Qu^$8cW8#_kLs~r7OF19noD)+% zCX)~YPaYxiv4jxmt|UbGRfO4wv5qhYx;%yJzh#K-?UA(%BU zDf~AIVtOt74-sPMIIQp^3bOBG`1cfiUqLY!fO|;cpDW0|kn}DEDQ85S^8x0k43PD= zk`VRhCq(@P36XEg4e^{k=Le*3Aw<6JB1Ak}6ug%Z<=Lw62MEDr;=F<3#5w#6k#FFv zA93F@UNZN>cwRr95b0$T!hZqb#fDKpi1#ke-J=~`N*oLg&NrC;wF>$btRh5u0fh$% zkuS=gkiJR5n-t`{g!B&pGM(Loc)y&F(EUk5mV>YW?d5+Fuj+Z^SsRWoG@Lh)kCKmv zrg#M8i}_AqM{&hC6a$D?AaET;NL%1eLs}X%l|g%Pq$B@D8=Wr4LWaR7BMj++Iuf|h z%E!*D3gDf6S%i>(I>=&0&vys8A0CJ(#`uI;6^$w=&t$oog#W**Lu^eyY^7-uG!v0Gw0jp=cRjnp#m zshZcz^9F8nw%93yrqLi{ks57VnyGnI@{x>`i#)0A-n;2*q)hTmXdkcaBRxs&Bb9xW z2fAeM9?@SGJEA`jBWXv3Zx|~!NAxccJ4N|sRR5_9>0c&zV@66`J29{LH_}~)r{i?P zbiqxad$if1*85XRqguUtpnumHhyRG3)OzairJK>;1xIQtX{EO240BSc-XDrq`f_7; zI5KYUG14Y^rkN;<;7Api|EIUBi;1gxaxQnU3HVo=Sa#HSNGUTxq&QgiFp8h_=hx7tFQ<<8|1XCenPtYMf5-2LH%y4d!z% z;MCC4h0?+sPX3Fj;cgBa4qn3{=2=zwrpzjfBCsG*2l%^@MU@|fU%T2Jd6^##I z*`!4nkbKrfryxK@Qg(7*(hiO!qLxiQXKd#~hRaARn^Hov?vEUi3o@{_DbA`q2vbfv zW~eW$gK-usOjd^D$yg-Si=&a!NN03RRb4ZTVEZ@@y~tEWsLNs{#PBmVb+8tU%Rxq|W3&{$t8qDCGO zeGfMdlI`Ba@Nnq9;c)6m(h6~8F>KX%ts*-BX1P8s#E%X1TG?2KZY(2|F6~luc>#N2 zfW!f1zmMVl(v;sCeG>mOAK6mKMHEwbwtOoQf)n3i^F8xkA|f9rLe`HeOeuU`;ZcPr z6{d+;Or0a%0-2v!gZYyLy?lHwc%5&E6*$8|#6-=xnR^JiFO+9bZdP=iqIp(} z^$8H`P*39R@{AVq3EdIpa!lhHcRuIDafR&fq$d=9rDvXgo;YhL&Wn7$(7iX*VQ7o&BVCB2Jhu)LKtVC2Yp1hd z{2Gdngzb%jo4s$}xvTZ6_X(bp%9edDgWqKe%#Y6{yOLcR3npqjfs55X#u^jJE}odD zOxj=PUEX5CZvWk#nYWkwjM}CXpZYqhlT*8Y%ktYFmvLs|CD@xWCq1vdpDz#8d}1^< z1q&fXGq>kVQP7-ejd>2Y=Bt{&^HzUV#~pA+`Aa(MCwfs~I}F6k$L_3%xKP6D;7 zMBqjEZulqR$v*|uj_Ge{0!aED_;=y&fG7XQK<$`Lc>;YpW+nO~JKI!nPz4!fC1Q+a zlnQc29mPJX_`on$+I66k|69{V@q<29IvNJqZ)#`F%v>$1sL=_DL! x?61x-oqSg_rtbk?4?O2Owv+AUUr1WF6+v-6a)ANmbT!;#I^X9$rkQ}6?{AMP1q}cI literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/lib/static/libiot_tls.a b/code/application/source/sf_app/output/lib/static/libiot_tls.a new file mode 100755 index 0000000000000000000000000000000000000000..c98c83baeee79f15ee0bae3ff291befa464142cb GIT binary patch literal 195428 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 literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/lib/static/liblink_visual_device.a b/code/application/source/sf_app/output/lib/static/liblink_visual_device.a new file mode 100755 index 0000000000000000000000000000000000000000..c2f38d38070ac035ea6e065a1bcf23d9e8405ddd GIT binary patch literal 2323520 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

u$A zD{n`smA8~=uE9E5cYhLf{ka*h*C^GhQ?#oe!?RhaABU^${52-S;9ErC!MBLI{cq*j z=%oh zF(R&y6M20qFTBpn4mtLGpwS*^ur0j?L%2pFc07!*T|%4_IYqlxx73F7!2-_5K1UW4ou?R`ZdRDn5o&#%?b13N8j)4Me-*5n?zOpA;|V@UPe)^>5KpI+iv1 zH`={?^JF8HUsG-$^BqN7S^*fI-wMERqaC30zE-Lxd5;uuKU? zu$eTXpC3im$w8n(rm#In5GN3mCx8pfz05F%9W$J;)3cYm>Bws_5s5z zEvA@rwRZV%isNhlhreR{c(P5`PP{vATe;8}7?*M*Bp*DGgwZUk5rK2;Mg%^DqyMQ9BK!tTmu-cAe~RH2`Q64+ zqt_}H8of^xD{wzwerEzM&-|P3YP?wR3s!KMdu@}2$hW847Js_ICivVT-i6>>v<<!$`XBq*ewLkf>u!&f27#a% z%s{b->KWJ__ge~=C(p=m^Ys1;J_mtD`hfYXJ6DTSVxgaN?wbkv{fNJ{V8a^hOaaIp z36nd#lj30r0gF(ZCc9$08{natOo#|3qPKqhqu-{0OH_q3j~Fhe_zu1GMuRC#KJ(pA z^cHt6=HkVmW?C4#JGy&>Dl(hd5J~j&*jJCT_>M>~euw=!8?S3aKJC37?!Li~yWpv; zp>}0}G>w0G!Jlmv{5e@YuSc*)z^k`~5NxV|fP7C>cZwdDANbYnx6wl}x_e+-q33f_ zHw_(fD#{WVtjXgwz?36~e!d2#TBFgJjVYtQ4p$uyR}|t}i!6&PM@1(g(#kTbM^LWI zaV{i3-DNpQQ4W^d*=DB?Bnt~<)b`la#c(rUZE#-t-*&Ix9_P%NPkv}C=TFDlQ!c{8 z60pjck>{CetnyYsMoc~rSrjl%a9Oz_YP=BRI~$p^?9bn4wOuF#6C`j;OeEL?!*0XH ztIbg|v|g`@L^ryxzGXB-bbTH0QLVeG?-(=w)QWSm1j1z;7n=GV1oRkK0)n~V-C(g; zP2l!!%G})SpC55evdYd;yy5~Y+u7SK7%CQ9!jDx5!voE9iUaa#HQl3{CJ7%_eMO!oCB5;jJdp`=irq!SFvG-Hg*ZR8nTBSks>uiA>vyZwBjD+gtP zsO;W5e&Qi}TYvZ!rf$Dp8rkiUQ(H@HwETQmJvHE~vZ<(E(c|$QmcL{4+2(q-{IdHR zsM5(|jYU|s=zqniSch#@qAaHk#Y`O_m6m;;1r z^IM0fF-NV&Tr=;A3s^X)2U^~NjSEUFrUT^f@2+%0D{+!k;o=##%X@-jozrlca6X-@o6ApqICAoPNgyaf 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

0C+HQyuN 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%0A^ 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

pe~;S#k4V4XhUM?lN1B*ZE8mLQqR36k9$iO_ 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 z z4XqO$oKj8TTJOg9Ibw<$*Kw6^$OcJx0CPRB^6y-o|~W>;-T)1V89 zv)R}`6x)j}-8OcjLzzE}hgy1$@U%_wqtz3>;*`7(*43Wym8DoNR-~Wsc^8me=^wtF zjFR{5NwM@iRl?#=_!<}dqyshF^K^-T+a%mB;SLVdKRhwygzrMi3E$}jCwyn{JGWrH z?>)ftoUf(l+0vhOFh!wS^!f1olav!ab_dGo*e0IO;*{gQ;^=R?%q@zVPCAU79rvA& zuFl@%^Q5fvc?@CHiodb~?eEaDXnoZ7*toF9Qyr$!Xt!1iT3|G9fxEnC@yzU1p0d2i zo)WEXOpc}d4c-P~ULCIvsjl%JcG)I z!j+_m36OtGbKOMRLaVO z&8X+|DP&QoJ?GnR;Pp0IwQ}fGHBGU0r|4QRbQCp6(uE=Q7GJTY>7#XB=@Hf04|$t> zHOfo>c++mn61LCAImH|{BjxicwxblQspq3_{G+AngOfE6#*Ca``EB~e_95F`T`d>d zO}THSzuWKp+wZsI%_2K2QqT4!tmo-c$063Ut@zCj=6(yh@tmu+)2bXfmZ-+5EqFFe zwW-g!R(4v=M~>Om@v7r!%b}s_&8pDR{;HBt+szb{I{e)>--YOcn9R=qtv%p+HRJhX zN<53->MI+w!*xSTF>C{Lvu6kC%`!*xX!Yp%7Ru!@7Js3=r}$?x|k`m(-hI-Uenp%eDIiJ zx52t2rSG(%g_siuwYK@X#<(upYTJAtL_Zq?dUIx{(r=;rUP;gFe{N^?_u751)K5TS zrRTMK!(p>6Ju_B4;JeS+3O+A=^w7nEhzERYM!z$v&{df6fN!ny3Ez7u4|OT#2YmN~ zW>3mbeCwS3z3+OrWh-hL&sjXI#fWmk9UN~%jZIhEe5*%WyQA0%-`uPdzWkJ}h(Dn? zab+9gTYA1-w!fH4#i?3*UgoWR0qk^w`ZHf!(gI)jte^Q#C$*s@e%A4Fybrq4Xt5-; z9m5m>YPZFACc5iTi|=$y*lf*}Hh}gZRh8%wAdRON5Tp#Pf$!{`whJH z^ix-FA+;2BMs79-(=Yu1>N@CO*%YJK|X^Uwui#Nl1+IY_<%HPPQAX$UvY_;pnM$JlG*aIR zDN=IX!&`DxA>D5~!X7cf@`pb{+%iAh79Z1T4x^Tu(`oMa1J}Krms#?PQxjFeHE_og zqK{S4(y+ZhmDqQ*y7y(W?w$QCXpaM=$FQim4Lz^5J0`-?eK0(^IY&+B5*8mmdfxYt zhK-jkm?iwR^^yJNIv! z-2Xr>&(u*)gk3(#?eZJZ^n{HT?asveo;F`2`a}2^DQ&QRX84_79ya@!+4%@OxjoS_ zTyrPocEQU3s>xiOm^;F2O0=C}@e^|P#+~X=lGzqZqltTa<8p*wE&jLpn(|RHVeldQ z9d$*toUb5Hy#aPLf#=(*{=MA+EBd@m$mD=mnRw%gj!E+ghab4`MVGZD0rvAiJw3UE z`rF3Bo9RB_p90WbVcJwW08O@6f_uXAXkkkdw2`m<%&Lb zyn@+nNA0=Qc>c?#0V?Hn5b`=QC;j4hLvDu!2@_vJ-!68l^tt`vCss0QGFg>ZdoW z)-8*2&-%_kKr#-6jID8ZQhqqX0PZoX@pe*k18uraDK>P$L>o`Pi;cFMa$; zTqVW=%D~2cn~DB=_uSZ6T6xg-=B{Sn!%g9%!?<>IBpG{$W{ z<$G+?M&G7Q6m#I-H1Isb?@>p}tvvkX-#&@go`STn1TDrIKx+(VFxNo%3!-f&f#a?kQ zN+*I#Qza~rtcPuYWV=aYwsC!dhMHrBn{wCL7G)}F)Tef2-}X^|uLE{vOA~n>y z2J7Sn%+!4)>lwoIqtAy>275l z8z*Q+H7oWAs)>hYUmULp%fS*pXlcV}6Wo;TuJB`Mo_nKY|&vB@4`DU;C^wR!M z$#t;9UdudTx^ahKK-Ja zgf@jqMq$-rf?7Sb)Lq^rq=PX~#kTCNzNINM4-1dg+-j0`cJ9SH{gVHw#r()YU(M(p zu5<9LN2_~$HM|ZX8TWI@R_(?QWteSIyI_NCs(my`8K#~-{469hC*FGInH)1DD|89T zZsPj7Jx9Q8ytO~g|BEN%&OMojT8c#Ng=3y&4b7p@ybHz%@eRWpY-=-jxQD-~J!M{4 zhL0oJT(0Gdn*Zo6bX&QsCwx)6NRn!*k8eeGE0Mo#7d0}5OStXuDlXq&&(w4ImIukV zQp#7G^J4qAyy2s*jchD&3m+|{wC|sQ);}tB-2PJ?V^T*xxe+aXqi-8;^|SUbM%av0 z7sAq0XXC$`IuHNnrY^+)1*y|P-399K`5S$9{L<#1>L|Elqi@lCN@4ka>)x9XzdUuL z@A>&vPtr5eH}dfxDj(FCmopO9;fc$G_Nu%j2l4+J1%n?jia!bK4p%1l!=^t?@fkdU z8UAPD$sR@cvH=cl%G@BD7T*PjT`kxW&&L^LBNiLNyBz%+$LAD6F85`PPrTO(eWo-p zb0zQQ!Uu{qg>|Qx`|o9&Nb=~92JKzIxru!A58~Y9D|Xt|7ko#YBJC#M66Z~OcX?m% z{g~_FX!Triv6o6n)QXkIw(@pEy7>lvmqHuX_; zi@M^w#A8gHRb{+Qi1_#AE>`EO)<(;diQJM}wpsTQU6{%eid)WhgeUEArFZ>)on_lY z8@n{so$3;N5S*wwrbPS(2A9F;x!vh?MIZFH!myw60>Z~C(I z?bjXF;?Lmme~0*#QXu{>+HJB1EZb&Zj8jCesUBlck3$=W>grK=pV9Dk@;=yIlaQ03 z>iwOuz$x}nUbf=i;~lzJX|d7?f2 zqB3}k%hEc-%i`A-52^0NlR&-AuD0Bp*gktISl2>8*b@L(j+y*o4{Djqv~eaya~l z)+bMOgw==rP=7kCN7g?JxE!Tar|3 z!)Vp?B-=8$A>B*zzuzwUn@vqOW9-Y~2Xx!Q(K|*C=#GlOoVnS&Wq`WT7vm^YPx&nC zhT=clw2Q}dyh`y+nDaSq>5p_z_)hRKMzJ@cIa!^cj#k;zL=n1Y6l1p8yw+^IS22H= zP5FDvs~ZL-Lf20#iGOKD->e9_bIoKMh}$39jS1?qH_ZEeaHT>raWz?WoSTz%*UbtlGZVWS=D zjXYhJaCeLF4w3c{>JK6sU+^Vx`<3^>H!_5uQQiEYH_C42UNSumQ_VX_Y9~Byg0t=P ze}W1d&fB&2oIGYh5z)xT5skFId&N_lTa9iU42wCJTakG0V60zYB=J=E4w_F5+uoFo zgO=Zo_mbWG%01h%qj`FQi{KFpkEQESL(>hI%k0;9lN!tO1&!vp>4)6dd2T56(U6d! zeY?olo}QC+PQ;>T%0$a=t&mq>{Tdm!on{_p-YcGxyn`EUkT)xx;v{-)`z+fNRA~Oz zupO}#Gu2($V$3VziC80`r#H(Hn7LT^Vl)Pe#Te{G!x${s8^c(50r|c!!k11^?R+i6 zhf(8ciySq|*;&j8^4`MI^O}H|o#**f`N)gUgKKTK4sDlwei1JIldu1p*VUz%UMt2N zads3|1lHYyS#tQKn7!*rQfRKc1@p+;5W+B{M{{}>E9RA#N2<1i!@O^lD{71yuYT2M z$&KM_VH#(1E~RGX^-HS=WKTk*&#as--Ip>mShC*eZHLC#iE>OFR>-*430+rm?P`3n zNCz{g%Q3T6h8eZGAG^X^QlLd*&g{Qj|7iUgO4f%}jRA5lcYirN4~%tV+3phJjJa@N zVm{o;N5OM>slM&o03YQsggu72(hXd@Xe^|SlC9lGa4%+Etle$6ZXq*dj$_$2eBGS8~= zQqQDSNmFX;m*8_L_4tTw5W&5kB{;i(QbqZaDYZ4FQv^B%3y)Liypbt#^_*kIyY;+`^lX;tM?eDt~wpFptJR8@HFOYyC0d!5%~ug2F1 zCbPgNie}8vbCusqDDc!)S{N)(GmxXLD*ojpNe=<}1pFhU+5M47N$aBuN#ut(YBy1wCZ zb)C_17Go_f2m6;VZx*>D-ziK*D>UiTC2nFKVvnL}FNKTIbvU1Cs)ofGBiFc$o@@VH z>Pv*z8j(xwAtGm7X*^amXPHY&S^VzO^}boWO^UT%vOk&+gmd>%J4o%=f1cGKi$Ruy z%Hj~W8hh~n5Jp3L@Jl=D@`fME_3m(mx6Wyf@G>vaiPb!@u0kuyWS5y&^eto)#Ef!9 z^Z&wQCi)*>UP0?w2v1SF+N+QH4p~Ni(>qWdr``d7#wsanhbOBqczfFa;{AL3L07+) zux^_o{5F;lb8H-Dc6~=zc}nZ5YG%y9H#veo(~L5o)Nv{AQCjs|Ge}*h&X}{ev!8jV zZF+8LCOp;FwAqxtk{GL|9aF~a>+ENJFQ(|tyPCJU5{^Z~pFdE|o+!>F8nzu{l5^wK z>S3?)JUG;M+^pw7?U>etIs0k$;Jz(tVPLu=6dtTk(dQMkX5MWxMN%Qc3Q2V zsC^;4|Hsyzv0dqI^T*cjzoPyUYXtdfWY2;7D1}SyU&h#sr`6EE=fK(+^;CNdW|PD- zWjkw7dJe2KBh9w%#kc1~Yn1_9ADLd&4Pv;);ccRtrwLj4REhNLQmT$jNt|nm}AR-LoP2r3F#uvV> zU$-T)bGc%_L;ZW%%NREeXbDH1h;V!JX^dLk>Nd5z{j@L2@sIYF=8wJmT@&DUP|nt2 zbOdVNXFR0(4vSdA7Gd>a-Fly;$qre3-)U4k+MxrIZy`KpF$=Y}d|a`TytYJ%k6+o* zzR!K3Rk8mKBTlO4O=_n10rdu~7_nW-mff9^rmC*{Ghgala&zAMOQKD!lSOS$jHB9) z`(9^czdbQ|Z_aAoiQ0};i@CMI`1IUZbxKx-Tp>A)`N2l@7x;gt`eRp2>wk4dhTn=j z*uxvMeyS=B&$>poU?!F44y%z$|89H#T+F|TJlUuIr5$s!JoGog(TdIhCuf+kQ2Sv#|$U+-WGU-#E$tlBL7ZvE$jxVEDM!`XxNrFHho`icrWUT(MJ zL#O4mCy90n4aIEUu)~9!2k?B?ju@DzZ0Yw~7N^MdMWw-Byt|msCh&HwG_cWe-qPaM z1+;%i%)4Qp(!AXjac1_#1i*o3#*FXZGIsoc7Sffu7Zp4+x4@Td;!gbkcT@PkiC9BC!We$2XhW2ZY=Q0OK#s_Y3XU2|6%2VK?9h8B~ zj2)E0;faAj+?lbnGB{jYffHnAHpvi9J1_&689Td!<4+C*;?9g6n!(|;V>57>nZpq7 z2n6EJjOE|p_)bH3k|CVxFL0T$12j0k5g!{M#+?~EMT6;64B@GU@Ki(iG(-3_{%)|% zPenUW1DBaiH_+40)WBtCGY#Q0IlmY`3GH4DTxNEQf&LaY5W%#^G!j4475aCZf&Mnm z-ws-F3H*5ty&`^wA%2FRl5Wf_(-2NOXakp-xeeh0Z}O9jhwsth6rOGkgll&M&FpqV`m}>NaG6=2Aza{DI)21|Lq9E! zknb@aPI=h~{CPmqN1{*B1|Yzx{L^$eg@2;MDLjf-5^iLC2PrqdjP*6&Ag{nvbo89R z4(F`<_r|Z#z>iv1;4-s24B>b1{8dmQ{1W-QUx#ZU1kLPDL;O2={Dc7-l`((h5d( zVP<|qE8_>(mYMktkqq}64vCX@6S)3A_TB|Ps_NPwKl4Z!!o!G&5fFz-fFQ4#JRnhO zLy|cpfFzQjsMJYF1||@am;?l`w~eoszO2=@7s2-88_~9)VzpNawbpvQ+8fZe_-d)z z2E^ME>m!x^>i_%QXYZMPPG-VGyzT$<`)!!4v(8?7?X~w_d+o>B50BUprQ`96DqebQ zJGYpB@ro+_;}uWhXC|28$z$8eP5dl}f4m~e@Mk;x;}uEzk8${qb>QbX@No|OTnFxV z;7)xBIQ+96c#iQlRD@c?CNY5VM;cUwI5j7L@x~Yj9+EigOaSAJi*5K+W3|MoIRT6( zZnfdljh!}phVdI)_@MEj4G$U15m7>(JcE53;uimW<9Ug*%P<1=_+5$9L7h^)%!ddbG^!FDtA<{9v+a36068FPzJnY+kNBE->xA=d?7>6o43A9u36X^xc z_;c_J7@sw+)2cAz`;r5{*?~U@ocqse@gu(j4u75-pd9&4aNtuNcs1~ZJagjb1Z+dt z0LBmZIOyMS;4TyFv_7f4`@WbHu7-$(^p4Ox==pqOH4d6Qc&w<|w8>Zw1lelB}1;Bpa=ufh))KkJY*a#Je2$y$<{j4&2bX z5DY)YflqMYyw|iCh5Hg{Dc?Sa|2bM0g!~pe@D||1VB>f$CBuK);r|G5mR}Bj0i5P` zf!2i~zf$0ZDBMf%%S zKo2z%^yi^Vb}#T-B;KfX(MW$MaPs50E`ag+C_fPC=wINs{B!Xf!1%lccp+@=*Feww zJP2Gl(hnK0Fe}d{I`CQtzSV)h4g9B2em~fd|G5DxewIf7aUnTJ0 zBm6wPX80R{yYT!LegUJ-a8psFWBAVkp8^~GEj*L{O5migz%O7l7|%H9-*n)UCV)^n z@>>J^58$^2&*XR1;Xj^=A|2_gfZv3Nd+<#9Z#evS0-p?Z~JMb|x?EH!y_$9z^g3Y{3#{Y)HKQm|# zf1v}v8~7yH$eU&O-46dZ9sVB!-wAqUZ^neI{HaCw0CIh{1OJ@FNgu#T4xb0kD$1gF{1-=2#R2$;o2fkgyUjTjpxL5ig1Wu=L9~wU9eL8*&KN0v_cutde8Sq1ze?4&J zGWnpEK;?8AIgJKxJ(`dEu?iZa%j?%PcSahc&C$+iW#SC{U}Zz}B5Q$BINZ=2uEzB^ z)0;Zl>+v}bfz^d23qrHXT35H>Fm#hEmFhdOS_^lj;R=ZOy-#`iXXwfX#2RXd)wf5m zAgQUdqp~54D{&ga;c(5Y2>v51uL}z0*R(dQigwC1SYgI_;yiILTJ`(}Tx37SeQ0<26SL^Wg&;!c9A)@fJG1?Ms4`cVqU?K;E?2 z|82;68^5nkXi7ot`nG6kVZ*w0p``w^)D2g*BC(WgW=*sc6{@xg%M_#atD^1U^^DdY zfw-?qBN2QYBzZNcI?+a}awL-yIbPq=*o2xG?XW9{kR&fy0q^E$Wecu2z&gfi+-eZ* zL|KVSH)~GE`j!Ukos2?O2h@INm1Hf)+n_~W+q60=N?4Vs6yN$jY^LBXQ2x!R^UdW{hGN@}SN>9R`C+Dqa_Sr2L}6Wya+ zDseo=HA_}*iIia2zk(}~PTVNtBEX9xjZMh?($zeFY> zai-O&c?C7m7HI4IwTWiIQnIQx+R_doL%f>mSzKI(%HA1W7`iYKj)g5KBw3D>0vtXN8 zbHYtngwx&}Z8;XNkX^hbm@go6vLvzA4~bHTooxVvh-~cOjGM>D+<+Ktt5vN z&s=d?t(CVb6GAg9%fgYx=At=sBMZU{=hjx((^f$5>PyR$c?!`*ai4@Ns*x(TG~8;R z%z7^6T~7;M9ErEUY?_KAiGETT-7x$|9>AQ~t*=e^{1AmNo3pUIvV2Z0o~kaYu38vg zSQ{x1n{yT~sI^gBsi6k_qf!$$&_a}u>}7}=kKTNHN4V+aWV7<>BvMrj(_Y`v(X@ht z09h%O;#e{kS9Wl~fPn%UY}LDmlu4?t$ZYFd}2Uxy-7rnJKKxiPx@~^=)ld+tP4y)l)I(m)A); zJhQ6XqZm>|Q*?GzDd7TeWJ&4z&ZuQT=BUfAU`RVpE`yjh#opF)3FScn;t^PaiRcsW zY+;K z0U|NcI7Hjq&_+nRt>h6(nHQWNjke8cZdw~%+|t?9T;0B=1s&!7J%Zw@#Bf#AoLOr0 z%IHN+2(m+dQB!kslk5vS^ncbGsr8ZN?e!~o*_mo8Y|$lAB-rnyLpzleTQ5!#>p3Cn z^@-OOv_)trZTZ{3HwSeXSU7D!DrFN{A7dKi zD@lq)=S>W=s9WvJ>l+-s0bL|Z{NoWx3l%CvpE7bav^E;SJ$0Q?^gn_anO({^HR6RW z+ltYbtZlDvK^MHevn*DRv3qk~zP@8k1ftIhX)m^Y-(6jKTne0X#Fyq$U5P1c8BBoXbW4_!t!8oi7vfR7NMN7^hD|~HFl!YSFJ&7@Y2%sEUye{=Rg2(k7r39rR4fuU3KlUwa7xns(Y;k* zJ);M1MH2a-*Ps06`i@TQnrn!nk#aOmI`2@SHTtyn&T>e!E@gerQyXlnNhg}0q>*E? zy1p?rpF)}*XJcoR33((e%-U%C3MG8fm_oBwH=!5XvH~f!riePMc#~4kM8s5SdkUS? z2q)0m^b2~-Rzb5@#nyB?Dh)@X_#3TXoqEx7HL{uxul~VbN!J>Q%8iKl%SPiwAZ2baLutpiIG+ zA!n-bil3wi@KGup;hddg3Pw*;LGYsb^~<7|L|Y^#d(rDj48YM;&yBW3+Y{f#FpX}b zz^t1-JkpdVKVLAGvv@dQU{Q2=b95c-ZoF3|lIHBRChK`buS&EO$(n+^pl*ZXnt77b z2coh$K9wb6Me6(i z73QmWBQ2<$fj#0golRoH_sB%;19MO_+>dgvv=7lc{=h zXMa@};)e3kg-d*hV%C8)HXM1#6eRDmmePnrSyQLN>@_SK@ zoI&b$7k#3$Cv=RJBQy(2WsOgXz9@s(en5EZpi{pQt+}TWO*feDVQ~Dh&G~m zwb~Kqw4<^}d4;9*9Ze1Vjxwj2UkH)eHLwo&Kopt@{ZU^F7oiI)W~(D2UzisuXB`IO zSy0u&xHwYc!VNK&u{ieA-_R^%d^NXP$E8Rb?f+&q7CIb-?3fIRSSuLJ7HFxSYnHB9 zeMR(u7UB3P=!!T_DwRRB6iDkX4b+iMZ5t^?V%(}vD-@$aT#QM{nFaPJ!|F&)plfx?9_{HR^t1SRf_tk{x~a@ z)zd>o5|#2K7|g^`ahw*gYPD$bXHu@xHOrTCFje1ZP14I4lu@@$`xTH3nUp-VeSTEW z*SvyDc&-ktip&*G{ac@vn4*)f$V$qA`UaTEXR)h67B$W48k|g7>ozPu*xxQJUN~oQ zZ3T{;yF6TO%a6R`{=}to%3)6~UL3Bmn-EK5|5;aJ>RDjZj!>~GW&OLJQdw10R^l*C zOB=6fVL6Gd*4SSf2TUNESUfrUsmM|~*>>?&UIzj7_^m~)6 zRS|);)G7{snb;#*?8ZB4m&F-1YA)MGXDQIXk|oU2O2 z*Fr3{!EmOs{3O*ukKS5ku%xwJ>T5j5APQF*B-2xdciLg`g_ECJ9bXOf!YUL*NsPD^ zSd?XQzWt_jb+%4VQO)zj7cp5v$NH#~BAuUL(k)(q_Ei+2LTh1|oG)sW->(#Ps?S$k z7%0AW**apWsG*yf0j=*i>Gl7*e(2R$&5$W^LrH3^voLJo9dlPUzhf=_>=(K7+f2Wh z`w>`CXzN(5#u&-f-swV7BXut)M_V%+$}6v|DVwvXJW^e?$lj`kW-TtS#(}U^wN+(R z3nB~WTx5NRiDzVC^&)e@5)m*`ds(%^w?MSt*aRFxaTX_nCxvKZ+3Vd7hNpHjUlVJ_o)goyt>!r?CC zAwtOeD4_d7+|w-mdF)3mYOTEZ-s!Skgk=Lf`*uOqQJC<7Zp#}R&r z{YHe7T}CwHyM1Fr>zTX1KcpoQ@Ox{Cyj>~wK5OVG#M7sAABK#YKxTqo{ z4KU;~vIz5B#uo`^xr|>ELO!0UKzutkDPEcXkzSC}~XEhGfL7Q%ThV=W=%{XF4(mvJK@ z_-&E?Tc!UGr2nJR|0fdfCR~7gl=yE6A>SVfA>TWM;P);e z%&2r3=My5_7YR|W8zuf@LL8B}U%vmNe4n0Sz0V{pav7ru&vzL-$IHDCdPTg-Wh|9& zB_Z^rUE&)Fb6v(g57?;)&l8NZbHYZCqqkmWuc`-CaqC<(_&I8nl>gh)q$#Lt&_ ziG-$v3nW}7VGAMjvWpPu*+9s26JF*r4iKWe{z!Pa%Sayzc!kRtNq8yhpM*0BKf)er z!rx*~Eg|GtB;n-}E|ZYwiZNYngvhr}LX^`w3A+F@mZJU;g5P%tuXGvD5JIkB5<;$* z2qD)&>3@W9nak)SMEpD>g5k#w14KG`9vS1CN{IM^62|BczHNlyyH>($32~{$^@NCr zXG*Xf9wUT(eMaK15W>FvQQ}7=?2~ZBa4TFEVGR002>E6c4uKseY=WI6guXOOcnx78 z>I-4iW!y}-(q(KSTm^Xuk?;2rf*;R2WBMK?MEZD!1>uttJ_ATT9}q%bo?(%(+GPwS zMEDB{-$6YlguSaKM0%G<*hbh6Js|}B%@S@Tg#CM*@G6(_JR#bvR|s*jK_B6I*cEKF zB)?2T)Dxa@K|Upf@Lwl!o@?g5#%0_>ycq2R;X0S`Bq7S_X+o6KbA%|DBZSb~j|i`Y zex44Pjdlr;`Qax-KIBL^lm4G~8J7@(-<5>m*C^pi3EK$4{~&5a-vIkZ2tBx#@J8q{;Y}{%JA|;`-y;N{ZSwuY z^8MrT{ZAz1d2^Ka4dT$#cL@IncAxN1@WYuK8DB&@O!y_}7a`&=lJH8x>s`i5Lg-;T zA@uMXLd1WMgxe(CC*gj=OVG{`Zb17!3K01oAO!#O36VaY=|MfHBZM9-CoDyMCWIcX zCH%lJx(L4v`$mX(zb4_W5^j`mA0he^2LRo_$9`tQufX0BeiiZ%BA<^CB46He+eZjH`4(Z3%Xp9Qo5;^BK-8~HLWCbh zi10;($iGs;e?k2rMEEmJmWenhB9#>j-}fJt4dc_LlG?oW&sFMhSV|A?xKLm zgwTWS5TDBtbqACJpMxl8zLnuWhZh;sh`{f==3E(6_K5f0rc zBjbQ|4g&R1ynh4lq`!cW8|K%@_#@H_=R};vyYNPC&}Z{Ps(jD`8N=A_+?* ztdOu;!b>DPk8mjTju7cPpAdsDAt&@@nS9?u2z_2li1!=i`+Ma3hvfS`^8GIf&p`c< z@86a0#W)Xqyr>%FGn^3djwM9AIr9BXLg?viLg*<>kw~w|2hgKA5#=EA;ZN3i3>jmj z++el<{wx=!m*rVYSZ1BEFfNGt$nda(qa+MSIGqsflSn`O7s~gdoPdjR0=!Dye;??Lc5F&Gj5~9B;;z4=gC>^1fLjDNsJaIrjVI%tCgh(Id<+$oT!jG);B#1vP z-@ihLdVwa$aIcX13;!Iv8rOh+5&gkuG$Hipd_u%?Ibn-T2ka2H~j$xJ;Hxa;tvx77jlB%0pOHxINz_4>0B%I?P@E%?yD_*9``MjKj~m! zM83ej@(FDE$vf|I^SfBOhdX7GXa64}|Yw+(OuGovq^DYn|!k-e;Z7<$lo+<>`J& z%DY|43n=um&SmK(@FnB}xKzSA2^%Gh5&p`+X>}GI%gz05j6Vp!i~c9!%Qy>;5S6Zr z@Xv;EBjInXvvAy#Fwa2zRkUk_uUTjEFy5`i0UsjlLc2i-`X>pIpL+=JM>|4@@Xrz= z{PTow`j{#4C=uh4Mv;VP9d6=%$3|i$> z8qV9={8e`9Tl_86(zzt1O3kak%mc7YLfnsY($7-1lL(S0sz2{koA{H4Pb^f#Mh9zG z$}#99~M&Ig2iuUawZuU;wb9y>$&oHOJ?81~;ax}+V-M2J446jqt-2uOm__5r!;FqdA zw!=@+-8lf=)9`}|34R#-P2Q|982cTnIDqc)Kq?C{IKZ@?2 z0r+8xFHVQ)iG-^sZ&eN%QF^!&*E~wGnJAizg=TrPJU6ztxg+_mz z2(0H5@FN}V7oW)w)BeKUF;+fEKtH-E_>ultbV1Mv`P_JbBR|d=Dkop#v~@e(eV|i* zq*c$W9duhkr_!j?-R7WsCjRzf^IN~bh;-~(1jdyPo2&)*H;Rm;Q~bW@pgRaU+85;%-Sv17 z`X^sx-H>Q63qh>(kL$bic;5p*);Hx;S>NU0=Lf$`5K*6J;ivdL@8IXd8Tlg=Ge9Yh z@vMViP~%su@q5?7Z!Gvh#JE%P{mH?v1pKlX!3nV z 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�Q<;R*fFdEfhV@_z136F(>K=Lyhb9b)|0 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[Y;8$8N{t9jWOX8 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 literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.d b/code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.d new file mode 100755 index 000000000..db60ae461 --- /dev/null +++ b/code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.d @@ -0,0 +1,10 @@ +/home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../output/obj/4gMng/sf_eg91_gps.o /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../output/obj/4gMng/sf_eg91_gps.d : \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/src/sf_eg91_gps.c \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/commMng/inc/sf_type.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/logMng/inc/sf_log.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_common.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_enum.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_struct.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../hal/ttyusb/inc/sf_hal_ttyusb.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_eg91_gps.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_module.h diff --git a/code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.o b/code/application/source/sf_app/output/obj/4gMng/sf_eg91_gps.o new file mode 100755 index 0000000000000000000000000000000000000000..5654b2420014a6147b26922311e3cfca434de2a5 GIT binary patch literal 15616 zcmbt*3s_WFmhLX9ikG}ZjE@*CN)%MYq9_&c5s2jxf`Si{HWPaU1%qis0;Lh3pv2gT zleR_Ch_N+s(nQfXq}x#^6G=>`HEJ&Hb$T+1w{d!WhD_grkffr1=KlXV`xFOa`u6?q ziR=7l?Y-98Yp?y@MK(;IshCVAp+6>(Ai6mreCcYA)ulp$2p3^u>}_w}k+0*|MIROM z;mRgu^Q|zErlf4i>x!y)s4;41|6Nm*(7OIj@2tx6nu6PW2Uql|`)bt&_bDZ^E~P4> zuCgk;?wzWzy4QRy&c1cue|!J?Hec=dHSXZLHeWR`r0#Q{a0uJ(8Kwklhsiwb&Zh5# zcYe)@j(|wveYqyMVWcABBhLqY6ds#WZBu9=q+y?Zj$*cn9pui&YN-Lk57;l>7L{|9 zHebScvu%xAE6s-Q*C8)z>X-n;QcP$!@aI#<#jvjqotf1E4*Vi(z{fJ-U)9jN?+yoEl?2&8D3M(^v=v_ z=Gd0baC4ilpmunH7Kb+9e3#F?&z>ng7!+@eQk!qGD^oeZ((2c^O}jLY6Om^0;4D0N zznUI6qzAvK&gcw}3P(@)*IV9SwE2W5&l?a-?fW^k$`WM*N=#GMxM5d~)^|BU%0-`T zn;NmYHSRXwl}(Z7zjOQW_30bm=*Io>{#Gsk`=TcFoz z{U@($bGaU^ANEsIU7B(-M{5Im@XtAEJ>q|E?1rw&qXF^FIl|VQ{idCLMYEgHX^NV3 zGe>z#c|>{h#+g+c?KP{+HdmEnQoYZ5)!e?x>_~gRJ+r@KGQTbDwH8zR3#NKs=(Yy& zZB@N5xZ2$QzIpuG=hiqL-RJ&lbws<{QtyknTJP)E64d@;P*B}l9S$>E?y6%-y|3@p z;Px3o^}d*Guof89U~PXP_@XcF>aaVtcNgAy@s1v1EIW}g=Gp!_Y9*9c*5e zv+&N=Z^e!(_eEb=^_$%gV<@Qi)b*{MK%P~ z^=UBGJ)5JApgs*5oy(&F#=Lgg+VQ zrRJ@tFEt-*ZV=*bfH!Q03{#Q>I^mbEm*eAlx0{q`NERc=%J zzx6e@|GT-5o8<+g9F`K&zRC1{yQ%N%?KPHIbv%f~6Q@n~(9iqs$?JM!T1%(NY`z=t z)f=Z2O=}(gc#5*x9rUsJOlWNXu;IRdF%IRC@?o<$a)#z) zbdHT)hj}MzJZH2~YAnviI#e7qd=zHfysq69{W;p?{Ms*Pl#fG>t5vm1mbalrbfi?b^IP=!G_4)+h1CdFuC^r+$rjs?FzGPmMO8V`^TPqhbT< z7&no1NRxHc=KH|mX{cjH=NYUk!Be~IggJU@8p=hVfmuu5X)Ft)54=TYUwRM>*@;=a3&@j0>&`PE4p0jZv zW{NXdxy&|}W~$f9V`<&8Cp&&0Y4ZNPp~NXD@$BS`&gY}0W_3u1IdF|ziyUGzBtz~a zYOq!d??lM&AHsO$d95MZOs=&aW5qK6HvcaAEZcr8B0~-S{r4vHo~F0Z3a)qWxbM0{ zJK{p0LP@3x)IQ#9RlR!o#Wvr-AvR@}^p&2z^@63rrkFckHJLk}3&4IVb{ed7J#4n? z`=T$`^z z|A*Q!C0Ww<1o-~to<{g^>(F=bJ)|Qpq}%sT)9HI3zwg=XpYVMj`b*0f+&i`GnXZJz zGlE**{!X>P9?l)8-qX38N{q!W%AvIl##y>nm+S}B#gm@hU6&X2b|^sV59<<-y6Elj z!NxXUhFX`&52#C`T9>dN)FlRWiAkT1y2PwzJ=VA*&$GYO!v9D)I@^5r()9kL&(eDA z!wvJ>r)fR=&V{rG^_^XtyL~Q!&rPplo(paBHJ&`Ce23A%HsEMrPYA}DBT)HOGyDDk z$ZomKsMo$4G4ij++$?7LEPd3SYgAk;Ew%abWgQ+A^T}z3m~Yl&o`BR|F&`(qqYVBB z!>8a^K_`2Aj?>D(YGpmf@A2j;_lXXH^HN{*wri_+F5s!a96P*#wa~n4P5o=5G|~{| zrqrHM-kwKIXMTp)jet0g>thiEttbarqJde^m-=@dc@<7iw!E=3l&WGpMcFj;4(KG0Gn&0o% zi5#0f{Km-ax6z9Ek-hmhFVgQiUtr5qRX+FND$XCDuex|UUeCz zScBekX0@Cze>m6l9iHi5&lgNoTf$$T*;u1{^%u;Qj~MFX#mej$P~|pZ#_z6+Z9om` zqV<%MYELOZy`!Fga8J26;ji_SXhXa&Pw3fG&Q5qxPdQ_lL-xbJ#+95857uvRe}{P> z+aK}W6RfD6LtS|TJ4|6%Nf7b>ghus8@rXJ5vUZ}2{JsBN_j?=WkQdecQo%~CuPjho z?Z@^@gAD$=dikFK|2h9?F{ZV%i0{D~y{8X6Eo@U;!?C;5PQmxAbCgx;N`f_V{HczV zNcxX4?KO+g4pS&<;0>!4J5H!$p?gMCcQ?1i;%vmB#c)?~0^cmVdj>f-&Vjp%Bt%d< zX})o!&9}RMURPs9n{UT>ZGReP*q`d2t?jSxKr9WLl)=iYDbG1gbz=K8b>-(gv7o=n zuzzD+_0{ml_97v@cV|Dc7ZKhIoAeR3p)0oOA8(2s!|rVTMvbSO@uP>!7|i3o;4U!4`D@D-4>r_R$l4lO zT&-=gp|-z0V(DcsQny!`t$1;=(PH-(eD&%*NxbO_fp1#xaUE&9LBFo&Y*eGh{l*&i zDRoA;T5~m*kuoV@!TTI>AuB0mz05)wQbZ}Hsna>^~WM` zo(ByD36M7&=X21fpi`hm&^FL3psk>_pd`?5!h|>k+5s93N(4oK{?Z5fpie-DKzl%I zLF++9pqU^yC;=1!x*saURnVV7XF*3nO`x@)MWDGL7ia=#2q;j}mmw$v^d4w0Xdh@L z$OCeNMuP@}?gyh@z%PJjK`o&Dplu)zXeDR?C`(ctFc9=jkPx4NT0n1twu8z+b3u=R zMuTENoq@0o`WSQyv=_7wR15NeazT%SMuTjiZ*Xt&C(tR-Aaq-akYt`97|G(?QkDT6x_g(*4 zbwgL*w{~7zlC7^+BH?GPi?h2|ru*Oi;dFt2{A|MNwZ7}OZ~qiCh_+7fX`BYV9m%;i0%y)>gJ%|1wd@ydE9@==G5JDc6JICtZ(>PrDu!Kk<6s z`0>}n<5RBZDaqF(;>TV8i8A)O9epVV)3T0l~Gs^qAH>qBh`8QW=>=icFCKPlpA?@-iNUJ|I8P2%v|Sl z|5wfiobO%1E=0mo_Zj9c4$3ZhFfNz-Son#J;>PQ@MyZX)!zx`3XJb&tb=xTf>s|GeS|#8GjGt%}IuL zR*m^pZAZ^@V?@on$nVqn2kg7ezhs%_SA~seQs%!C-Z3ONRqdT(gvH+H>-Og|l%Sm# zZwEhd@pdRE?1>09CZm*4dxk34(k`NLuRIU;%KhHV-YznfH|_>FtK4(dy9=&$=Y4-n zK7f_9Pv?IQ((YySlCru>>b%+a|D~i?ex#(E$y?C#vanur4zX+#Bi6WwDYZGSiM;D! zEjQ*I_65vd# z$orIi)d{$vjaB#GCH__s36FM7c-uNQqw}@u2Hzyd@RR@I3vifH;FqHyr(l-m+d8*v zywSg>;a`AL*ha~E%vb##g%#dkzO2b0yJ0o?M-AsU90$MY*f_pEQ|J=}c zbI|b1H%<6$%ewRG&6lv=a4jNj1Qmd?KuI93M}eRlm>*sNtp+86qClab0MISW4WEEo zKzl)}L90NVKk`ATpwS=;=nKpf{2kx}Njrd?LtHa#%a#|dC@r>?6js^_ODl>Ci>hpk zmzR|lFZL7{#m2^lip=~mb7st*H$Q)F=A+ogh|1!!qQ_P&8Ld8{wh@)KQ0=?dI~4nl z#f7D%`Ps{g(?=8~+Dex%F7zy2UIqqPqM~@^-)ctqJxI4DL)GY$J2PMN%OK2d6it?+GMe(d(%C&Nfio z(`Qbx&&`~bKHAQ9$jcEzHHGh$tDj$5<|(cyEB2^*S^4?1rztb0*wK`p;#HodMfSuI zMd4!Ua*rd~=}205JP+}!EY@O#-r(&a0Pl2A=GJ>{8-#Yu~nmZ{~?7uI{m^!zC_{Wb`pU7CpFL~(6bGW^aG~!xoZ2gqU+Mmr9YIY_953St%_rtgV@&5|KlMarZu)Z- zi+?Z{dRNIG8)(nWn>NMC1UaUs=eoo7{%B+6SZ7%!_^)a3&s7pZbQB;;F^D}YiV&O1 z#M0$u&*%)}Q2b0<^1^4zD;HK4mtqF#=F2OJ(G{00eWr&@Va4K-Zkftr@(a-gSCo2$ zm@#cyx-DTw?h~VIX-UaR4w30Z35CUli#srJ#_}-Xn7RFp5%=pjvn0b&eJZ53VWw7zFifAK?`~l$O z{ApG(1mD`<{V>rgV(~8Er}|jc-!|9kEb_YmxR? z1?3BHhSMHRo@YRvFUCisLH=jp-!<^hf#>?BJy!8NKF%8Wb>J@>_)Xxw2L9*ZEm$kH z$0~k-k2nLr6THK~<8KB;hJil-zR1A;8hp8dKLWnmz`p~2hk-u{ey@Q)4gP|G{~dV# zcCS5FaULID1OEr`1O465D*hdOf`R{E;JIhe9;^5-d@L~Vx51Yi`2P)_XJGBIim&l; z!oc4J|Dl0r`#B8l#s1#ZA20PWsqNduPA+-ocMXy(#uNVx?v}w`5O|+~4+n4Y4=bza z2Y!fw9|S(Zzz+kTXy8YHcNuv4J9%(-`KmvUbo2Tb(JTUcjo&~q2KM+wflSDs0-oRf zB%cR9&X8Zo^1(9%ls7(RflCp?V;25Es;OpNvQ$DJ|I{%Ojjv5)c#)67k{`H zf4Ud{MKAs%@P%-*6}DO4e}GShTVbdm`P;qZJ9_avt4=|DCnM&RkM#FdElv;h;veb7 zkLbmV$|Vc+H6v-Uh$|9FGp9NDO6JSSR|;P)zQ*%4fv<^trSg@=SF)y}>Lja5$tfbv zqh_g^$*O9ys++7TC#%}Ys=8BEcWOnd>Q1##r>g5zb)BlNQ`L2MZU7U0vpsN)F>@3>(=PG<|Eg${AUzeTwX;e zljvDqs{Rd7DE7SD(04;;;?9sb3wMpgT&x?C=RFD2yNG!>Pod9JK7)vKu5Xn8d&!qe z+(v}_Q6l6&lYs5a7 zpNV1EClDjB{t&|vKO*#fMCjcka+8PogL)PsCaGW|i6|$72st+qa#_R}+>^`v*%I@KeTA4$#Kvp^5%V1H znAwkb@67gSCL(^ki)Nf#CI4rMfhe2#+_#u9(GMiTk0C_V*G7ataYXo&AoCN6pqU_+ zx1Nad>WQ$okBIV)Oa5btyhmrhia?tY?ZkOl_lWtp8z;ifA|mWOON5-J2o_G9|b4Z*_M0rmVQQiU~$}1wm4u2=0{8}RHY?u7&5?hJTza=pYF`=D@ zh_Ex12s`{;f_A17VP}El%O&n5!p^kl!u&CW%*wusmUR-z%|&n1|mzh>#D&n5KLL5%LL=pDb|+5%NcgkpD=ge?o-(Ey>@L7>6;) z`6!DByR(UqE0O$KiEm1Lj|lsJCZayKh^UX3i1K*IqMcwO>#o!GQUysrzBn?qTG8#louVN z*&j@VJ*VW|5*JAl3 zgxp5S?~urSzZrYKV?@k#W5uQLBK5qh5z zVdn}F`d5iIj8kGP+MfvhFNt>a10u@rBEr6ph)wxD;&AkjhqQbP5q5)#C?|{v`%yAK zh6w$EM92*xjzoLQ{5YAOK!koG5&909?;^%yeIi1CGBE+`lgxL^^eiIuXA+@5Tju8z zQT}`)^cN6E;VdBYi)4BU5&ES>=$FfU4{V|m`R~f~79#XNBtrkJ%)cP>TP1&) z=s^3+^eaT@T_r;A8WHV$i57_ml9#GoCrG}$*&^9&RQbuRLlHYBF6p}nZH%$ZCl=ONz2e8icEdCo?JUIGz%Qzf4(v6P7U zXDt!>FG>E8%x@+_?_y#?dw zBO;FXh@4L_=dqnFM9g2o#33k`i1vsgLNA60y@4`)h)lQ1^f)5)6NqTPMB-TVCnD^) zh_I7Ngq^uS?i-tk@cTU?>iZE9eqWLNUnGX1&ohogBsz&t3Xv``i}(}l2Z;00kBCp< z_a!3YbdU)7W+LQTiIDq@2ss}SayHbRexwrN*W;3(ON3t~l3y+Hbt3%wlnD7-GX0Lk z0L<;w8%%`VM2Yhy7RdZnl7C5Jqr|gB*!`2_yMX3N@Rx`<-;*d1dvhwn1`jiwOOh z#B|IHMCj!cp*Nohy#+G8K&BVT^b#WUONkig<&yUhF+Yi<%Bp3a!bLzFt5qz~zbcAL zllZ%kNWu?cg(7KDWu-`}SWbr0$w|0@&{)CWik20ZL9}eSr#K1s@nb7Jg^PbCk}~Jc z;*UrbOBb#16j!3azwNsO674JR-Yz=EhexmK2TTX|8H_wl2jc`+3G`k{Qt7_ho7|hs6-s!)#o1eCOPt( zpsUQlH|1%U&kW2d*kbx0=8>=!RZ-7)igS@7)($Jpv5Qnh{eR4 z616EBo7&Xmvj!j6dM&9odJ}6&YFd(O{Y)+?{&ESL)TTfuakMsm|NlAbzyZPZe$y=e zv-VzV?X_QPKh7CjF*QrISS*V1u_)0>C#NWDpV4yslQoD|`YIvH=r3Bcm0_d*>i5FI zukT%Vx7uF~P$SiBZ)i#I{=TYhN6vP+`3QY?;6%f@w>K|_Z9ZkNIDQnz;JCX_&N6j=#w994fT z+}PwRTsd5=aQFXX|KI-jN`EErw-J#JHKv%-fvOViYW3UHF3GDc~=wxP-ATVZ(8 z|BsUk`~TL75+;NU_xY_c`}0%ye0~o7Y4GpapOgMQ`Lm*d-t2oF^c?6%U0bHBH=n|r zst#{{d?iq^{&q;@-Sj1Q&pvX)`p})w*7y9*yOtsHq6=NYqn*#-Ws>ct@ll;+81N< zH&^{$_|28pA2#{U?E`HF?d;kb-N(riv`1~3(K~v33`Xyas_YympF?I_4*R9b)^op< z*^GW!bvX*XpRR^~6&l>NW;wRoYgX~ix`=A`w`E!bovYmXIMx4JWG3ii`ziSB-4UhU^i(@7W3Rgp9?dk`Q%3hSPn4S3F}CYR zEA6jV8Y6tNH|ua~c7=Pq*tDvT;hPe(wBawAESELwsnls3njel*n^ETNv*{AbyL~QA z_6|C18UD$1%+?)i+}0h}-5*b1;||!7X{wFVdbHB^iV~x=zFGMZyz2kQ;i@sG9qJH{ z-3g<#dEK=QzN)N;H}&ww|EIV6^R8#4%5i2Hu8*K!eQp`cdL2Bv0ntHeJy3aKMwEI2 z+Uwm3-P-O~s7r#W?Og58RoWgHe7XMvgD#tU{gCJOK2KE_er$ih+C}d59^~e#lfP*@ zq>uUv?+XVvwwNvN>Omt_o$ztc0~fl;RrerA%V#<)mmHeYQiWEXt&LpkF3Z?}nuABp zWo zE+|cC1TYvB0_q29_g9p&LPvo$pxvN7ph{4VkPA2rGy)V2^4S#SBIpy)+o02+cR>3< z>xG^Ms-SpKA}9pZVpWu8&_|$?p#7jKp_RZ~6RG$fCZqtH{dD>WcmT8oG#8W%iU8fj zM&TIfHPB|z7SL+YT2L{l1hg1b2$~Oi5;O~x1M+|#0u}#%_yOPKoa&g)96w1x@vW+=Fv#iulg@DhVAd$78)F-`Q}%%-u=E$ znHih%!598>qG~_*B5=+F>IYv0&FQ1%TdG~{rv@~65>&reKJY1(x;Kr8WBq?0_`AN5 z6Dsvs`Laab3!0>>{dWU&Nxzzr+J3`YtwcZA5OPrG{`Pc&`hh3gd!=N8`kqfI)@6V7 z_1^yHPGx)dDyf=|9;-%gsB5$KPyV>B&4#_tSa1QrFkmq7F<=mI#s{gB{(WzMF=e|}SiN6~iYX9L}!zmL5@2(F>P-kj&PnR{~-!Kwrd)^7nM_7LO zS%><}3Cn|e98*Sr_Th7=OaGGRP?uO4EgrqiYphxyR$aEL*6Q_I{r@ig(plS8TKYc+ zSY@sFzn7IU6F$X0?PoXK?2%0M*r_y>yVuXEweSShUsbBJz19-LS7r47`HO$x{h$8F z*Nz4C>Rq3@AnkZW^Y`fMUpwYl9QLmrbCsCl51B@(zc!9kU7C+c&y zlT6x;E%C58&>8Qs?&$RT!p(T-O+RBKo=7V-nZ8UCHI{NKLXnQkQJ<+4}iM zMPdxZB`Q1S$^Hg=#=bE)+qv4uBv8@{kdnD$ z+O?52^24{?oBVe-`HnpZy3g$9KVDc9uNbDtly_0*o~F%|V#`!MTK z-naL9)K~BYAXotHqAf$%CuWwrJm^pszwl1)_Bw_ZdFfw0+=pNQWW~ zevj(i*JSwGnnho)hV<_1`H;XKd_5D=dz+6!>H8KU_5RvXfJ>C&QsZ~ zik&@Pf1(a|87U~eHF&z#a|x;iB^$eQqvVUh!MOWKP`mcr8BJ$QqOk_E-&|V1)x%=# z5bTeVFt&nS?Teg#h{WY?m$t_HVU3@RleA4cNwZ&aFa|ddVSjY?1${MoLXSG9aoWy( zoUN1#n?1LZbx&{)rR?sPefwb{d@{`f5;uI#2J99~=GO7!-qc>ge*kms0y@P3&Gi7G*)ULG7-hjE(=l&Zn{Nn_6aI-$fs9NP} z-;UdkiQ}yfeJbC#diNFmfm$`n%{#@J2ap4QC;`pjuz`rX+2f59=PjQU)NV) zRJZ?dgB`aAu2x2J2V%a%V~mIJRIZIy2X8Ycm8{X?%hdMtDb~o-?R~A$YK*oh@+9+=Hkh~u5rg+!*Rg%ezJG`Axl(^YTt3! z=l-uW`DzAneYAc(R$_VQYFRm`bG3Y`xye^HsJGTev>L>Am><~D%C_6re^;QbhX@(p z%~SemtAVFcH5sqquD8N_>dmIl7Y)siQQGYrKJ`UcvZR{0H} zE(UN!j_HtR8T!p?h4;dtBcEgT4eVSOD!krW_Mg(qJFR_-v%P60i0>&@$9lI5_s9tn zJ*oqYUfnjZx0W&H#V4DL-pmh3Q0GUmFZaovhtZQ+0YN=P)rs)k96|g{J(+V5V=Kjq zolnG;HEzE)zo7fo`)_Q$?!&A#t$>*4kD?|w@1d7HM^wYlZy|Sa&UCc!MSr%iC3zkE zbdBx2sW#Stlm0!eKKuQk6C?dGlV{>|6bt6WLle5LRB@2Ul`uG)lc= zG+N#fjY4g`N27mwZjVLRJ)J(i_4zdq{R@=co~7BU{v9dV-pM6?J9MvZUAuPTZ=Pd_ zq_#E-_Ja4{*yiO(WG^`{nn%uMPmpuEsh5JY0fh>A`{K?JR1bO|^crX%XgjD#XeKZNG(up^ot6G5?{enOx1!Pyyf8nhquBB&CS56TjX2RcFhK%WKU-V{^^ssZf= zm4jvpB?6tGn?Z{54d~CH2GDDuJ)q5?m7q8wC-9~na-as#YoN8D)u1OqGeOayfuK;3 z9n=_zdj!xC(DR^jP!VVbC<_!1a)R1%&wCN{KIkZDr_eUwM$lZ)L{JCS`eTh5WM$j>#THtFS-T~)>9tBMVrGVlUFt@HXyfx6nz1@%Gj`7yD-@P>ey3r+l>!kUh86X!Z4&(r7_c9~&=hjo!`D5MYtxV$ngqQoah4DqHBlPaUYFah}HTk=D_KY+Qy9~Pdqu} zcsJ?HFrr+&-1XuKb8wWlmmZO!$BdXl<38mQR`>X)Ee~KPe_*})hC3(4c$$rU#E?qW zGR~o%I=afuQ=qH$H`?ure&4%#lNI-O*h4JoqXw(HlAcYp?6BaOAWn*d*SnSNc4tnC z;cHh<&j;y#8mGceKTjfuI~&8#_i$2QzB#5)-(4%MTjA}V!Jw_Ha2soB%Ly>~(<;^Q_-W9O9jV{qME_!qJ11#1-YvM{zFW;nvh6UQT=G=45%MALjZkm8PvSj* z{%85O(Wjj5f7Xd!%KkE9$_Ss|?~{tLw=bm6c(!bhQn9;)Z#kxurQz8*!%;O)v;_KsxAEmS|fp5)$+1|A!)?N0t zTS?_IVjo1iH+(EegGil2c)qrP|Qj7P}tRI^#$La&5ah=PmAM{$7vM;`cYi6nfxpPeSY{pEg*WNnmv|m3)X}@=)bwt+|zyHQ2 zA8n&;@3QT-yu=x{^B%mzu)XJY<*1wNy?!V_wW3vvQ2yT&t+FEhxdoBxNB!Q!iTb&4 zQ>Thw^du#RQ? z^+Vk0rtR>R$0s6sW^G_(?;h2!hB2o1G+S^}ig!=gTAinFqoqzGCmnf41Z70uf?m+0 zRfTuZ!B<=AFe;Vy8JMX%#g2csXY+_m$niJzXlFlG9O4KF$9-9@Xy3lBc(j}m867!e zJgU;30Y7;EQQ>W@orm^~4m0Mg6?a7y-r+F^{X(%-+Vl9*4pI&UkD)Q7M41>6l9k@Wu0cRlQC ze>-uP$J}o(_gX&t?XeGkC|-2$wdav;^jg&Az^K^EKR}s3K$#zy%KW@}sQN$68O&)@ys%f6A`*56!kH`(>uD!aGH-_FqZ*JIyOIr>iSr;b7tntaV0>jyLy- zYHfKIHW&?pWMBBEX1PeS@SkGgXU)rS#(5gVbI(N3Fwh9l08mR1&PkxNpd+B2pqD{B z`>Y1#2u%b=n8=3jpWu9R9`rV7Kj>u;&q6su6M+$+p+aBboO2%Zj?i)7cFV+MSDlKb3gr?$_qYs zqTPwTK4PDBLQm0Mzc;T%bXIoaDG5f>>lt{))>eeso2f;`dO2rY$GFbKX!=FRDWhZG zUitUw*{$`#*n{B>yX)Fh#0iK1MM2}#IQ2etl33WpCtVFOI3wLvGFF|W-jDbFl-BA> zMe^b8fOyq!JR=785U$o2H#B8q52ATh;V!yu5C1WIVm#{fN!I^{^YADs=)bbpU*Z%`IE(Vn_FDewUdo^OA$w}}C9WB-XJp>?uI4X2!ELwF z?!WQ;4NCk15_%+?tNvPhxA<>(Pf}mI@(zD|d9dv9&F#b1>4RRY+8(98c86Zub6cyH8Ki8@7rX4Q6yt>zRm+@FxigqvUwcVHA*6#XPoa~)~9rK=_ z`Qya9=ihI*|KScs-^X5}2a9?wbA$SXsZOlRc zgB?oDWbdrQ%9!6`1O(V;UCzw3s+q7pEn}6tNOtbiE>HDjs@5n(?F^nS^%k0l_h6>0 z>5zRsqaLx`kdD9nAZ$E{^t>+V!!B2|@%7CHdj4%!LgyM0fCW`e?n0)XG(UWL>mbOA_uN9Y)kWV}~5U|k^A zTl1TK6FT1XQ(C{N+}dlu;|(gzqQ6vb#9O#rgJ4^7W zyti^R=-yU%U5Az7otE`GLs$Fz80kj2f4h8dW{i3->hdR3YV&1l)SH*N7W4g6QVXa7 z^bzPC5ZB;pq3415plFaC^d-ikF-DKzdkturP%e;k@4Tdh3CZyj5|+-JtvaU8nw354 zi8ROX(s{%4pGZrd=2*Hse??J&qcE@3kylhwke9#8v1s|SWd)1M3i2Z(BZKdq7rzu{ zl=PgKM>40(o;LHr;rX!%vCiS8PSc+R+?anySyM|&mX|oDEYB}UbIgk`A0D4N_laQL zeD-wRz9%PV<`i|>gHCu*R#0BHB;Of3Jio7^c`ZJ4$dnX3yP}}9tPn02lsIGK;Q@W@ zEuS8C$uBJ}T2xlfA~ffjH+y!LRy?v+7L=4OS-uRJvB^f=QaanwJvC#_w9a-cEm)SH zv10Kk?GudFbp-3*yZx2=qEC9aRZ_6>e_=|ili~NGCB=pCd&QEn0y-W)SH(x_ZOD`s zEGjBkSx}@2An%UjW1c=<(sLYTOO_TaUr`q8C|H)BvuJ64&Z^=9j0C;^w6T#sB?k%L z-B$BT7cW>*T(mqdf5GAPSplSZizqsCyqqkP%&A{8pLm#l`0R1jsj)$E+~xYbLFzpK2mf~CbY zAQdsnWE-h-X2NIA9KE6L=m*Et!WD~6Zr{0{Wo4_}d1ZNK`IspWPt~XVcl2{f!J?Ip z0#4A52|p!!#*C>`aunU`v^$qgUma{{M?PGLb#!gRSO?>ZqqIwlerMe=(u~%>qpUPA zWO|QtOY@3~mM?OkIUS4hmJ}J4yra(Y;(}#*ow_s(bP_w`K;{fJ`~N!(+__B`!RMSz zj@$fL2fWWKLpGQUzYd% z(zr#-mqM&lCr(pS9$vm8AN~JGCgOlT=HlGxIq4XVvUa$qc0`CSvJzQnb9iarju<^N zdv=bRnKf0PFPa+|i;V6@PMQ*%7#|-Cz2x|KP?DmiL&2S_c;L4Ism$tp+Q zQ+Z34VO5KaRA|XDo8vZn_H2jRO(xEi&&ezTc=&dwGIYzm$rvHDn)-`t?gSS=IY*(Lncbr4Aeq=6NQr1y)k1L3bk=Z%v zIa42um+*-G&eT%UP=EF_%IbaHe0Is~vb-`ZN*!VT&hpa>3W~AiS+cSKv+JoP%N*%b z9*)!Nq^)PO+#LUjiK%^Qr}x;>WiV^&r7`fet<%4*D{U(qF3pGRnNw%b3;gHInKDy$ zT;Srh{SMlP5^SD3`>4xlgP6hC*x@k%rsz9KmSgn4p$Fe* zxzil+^j)i~w(}}mR6OPxbd1(7+@d7KCXS6wLJZPmW>1}=^@{8>xNK3sq(D&?6)i6< z$p4OZ&>{oJK2|6?l_pzVL{^7xKx+-%pRDZJQ`z|X-nQVW@d*nUR2D#I@sg)lZf9EF z3T#A|aZ6fSCh1%bJ2y8b+2R$Yh0GMW(t;9fHW$E~1zd7E?3&WcO7fPKE-onPDNl1- zQKn6qlIDn>He=36$N0E}xOgQ!5z=`Dc?*{)_z}9I_>UW%t^@=JrrRw+e!;c@wlK>* zmO<8V%V5h8zX;1vKPL_p-9F|No6>g6oNZOixqQU}2XfQLs^DO6`dAfzWq^r?N6J0j z_#xmu9cli`{rFyF;)mh;J`+C@-}jq%2Ff!gJ_+B?nfO$EziQ$i#P^VnYWOP|;CZ&v zKmN)zeDRq0hr#pyK>zsT7yNif$izPe-iEWB{_$59;ETh=qsvVni`E|8PwF3w!u;nA z7VXRSvf_R!S6Hi{0(iriRazMB@@p(I$KBo_-ntzb(r{-$j>$L1!x!t)(ZV2^Wol3Udtca z$+N%rnE17@$LB@*$6wh9{-lYo0^d2m{FN8MpEKn%HrzDvyTK<1b=unt-fiOF0AFe1 zYr)r<_@m$(O+4>{u9*0@!AIj+nc?pl@VO@beeit0(8%Y#(moT<_NX(}pY5@Bq=;ku zUx0kQNxl($qly0ve6xwa0{)7L=kugi6VLL7#dO+dd6i>2c`xLX@qVQK(dTEfwnJcw z-k+NjB^$i?V^spWtuFz}4H3CZ(+<#n4;hBw;+@GgA6Tlfs{Irz?X ziupO0|6(;okg0OP~_ z_1*aAy7Ak(@jJi|$M_BP*X`AI%l{?#vGIt>s3*%)aMh*l5%s-X+#+RIz7m%;C7yp0 z_$QHnlK3Z?f5!4p3jd7bpH%)C&p!#eil&pGDJ5uH3CYT^GEG2JP0(}`H01YPuQ>85D9DVlDIraMm49jEDz({#say5lt6ahmQp zO?RB8J5JLbr|G6@x~U1uf(7cF8B=mHvu7+=5SKa*E!iyvUUf?upVTcS6@AxLCKavM zEd}LvO&K4bU^;8aS!HR#($a!5rL?RB|8Z0n<`pf#h2e_Qg^3HkUxNGM?uopyQ%Z|V zmMkk* z@J_g3!Bcd4@dBLBwYy?|*Nv1a#Vg9hkm;bL9iZUtvPDaa>2=xiX9$amS1D)$f@wNx zM=qm0O{}owwtP8WVckN!2rkF|khn@wxVH?(2AX@m;5CZkC9cJO1=F5_t<4}%! z3#M--LXLX{^1miR?kW*-!H6A9A3%hhQ+WQaU$ZAX*B<8cxhLiK3Npr1j?YGEkNbJ% zM-U;;XQ<>|!gD`Qp3ho|+`k8}!+ZF|^>}}u2s`gfKHs~iolC-hOGJ4Cux3y%oCrM! z5qfDv*v%k9Z>I3&MCiRig!~~Q%aQz#h>-tGc>Y#^@&SmwwAYV_eD3GT#|iTH1x)9= zHcWq1@JUH87M}0sFuz*TUlaa_V4bADFT7Xqrlj-V!O`psK1oEmMZ#ALz9x7~@T}lP z!7l}G3i7;X#rkI_K7;cq5$ji|@L@#kskjekKHp2Cyn~2EZJ4A-OL{C38!i5xgL-_I ziF(|(Q*R;>8y=UWyCvO2gdTqjLOt&5sh1=9bBWkE&6o6CNzW%juaF46BFQh7e4YoG zUoPouiJ(d%N%~GnuOY(D9>KkmzmJFw+kPVUGPRO^ga~`bh|sGe zqP&yDK6p=ni29u&Lav?&xpR`w5O1f9jCwNnk z+ePZ}ykqT${ue%k2!Hsy9p;A-;b%AzX92#)MxN&)^23CW7Cu(^c;SypkS(zM{Q>M5Ip=K8uKY%ol#4 zWhByLueOT_0;zNGVaUMxS3xCQe|_{WJTXBqJa zSQmt^68>c(%0EDa{xKrTZxFswu$hQ@g&;O)^(3PFp+uxVBN!)Li~bg#zmKyzF<*#L=m+93_)8p)ekYDVzZ0V| zUx=`Ci5QFXBN2Ueh4=v0LEP$KMx z2_G(e1Thlh3&`;|SFnbNaq%h{@zDRI85&E@6 z=pQ9Q|JOw5Um!yN&qU~dBYZH{5T;KgLSGfk72HUKz2}Lrx19)kZxEq(hzNUUgufu@ zBf?%dVj1NeM98HG?-48{LT^m`_Cb@dgoo93sMx_ldCc5fOH-3jeL3 z6KiPj3s|3t&`%*ke-aV;3yIKwnh5<$;kOH(CvL;LKt%X)lL)<`SOcjyf(X5d!p{&a zC!)McBFcMF_*Vt@NqQ|2_UehS*Fc257U6w@vA6_belijH4+%eCu$+kY+Dn9=2Z->y zjtD>ACc=-iM3i@h2z#wW*bBg=4f$|E4-xiqiO^q6g#I!j^j{`I{#7FMj|qQP@RHya z$+v~;@&g4^iSSb;!hRMJ_H&4^UqXca)kN5@7XCHC^F-+XnTUE`CBjZS5q546VJB=b z5OyMnu#+gfTW}!}`sGB}d!7irTFE~~gkHVy&4NC`Aw!T4`%WU{(u99Vu#5=18-;(7 z2tRic;pZOWYP?fUgq^pEu=A1dp9v1USI12{sU6^StmE zi3wOYh>2J?h)GyCh`|^q#1OPEF$Lp=I1cLuaV*viBJAHJ!j2LFgdH0ZcI-sthX{re zu}*~%Ct$oudIS;r4kGl25uqPVgdefQiI~Sk$R!gYmr8`(MB;AZCSo5}MMU}A zB)yslyE}=nTSJ81J(9my^7l#pe#x(u{3DWoO!Dg_|D@!fCZ=M2AfnuQBFZ~QM0pKF zly{zpad44{`Zf|FcZmqOW+LRSNcvUcRP;X)@?N5f{+IllMCd8^0ikCjCZqp}7$+e_ z_!CNmei#wug%hC{L4=+|(uYZUw4}!pUFd%z^plBG(Emg?`kx5g&s^mY=VS3`u}9wPMi64SA7Btm~bF$3|42>ByK$R8s@zK)1}*h#_DM97^XLav?& zxpPF=YanK#|A`Nw|B3LYkqEs@MCdgWp?8G{y{kl&(<;1|I34{j{7uPMhU)S*BINDD zhX@}ke37MA%< zcU<@{iO{p*tP%Voe*Z*-+vm5?{jpOwwN^Lhg|87X_P% z@aIb+{Ank`pJ1F3S zE)-lT$mh1!nHV=j#GB2;yD(0P0}$UOy_)z4;yV%ROpT=PA=(kAh|t?dgx-G1uO&kM z2od|OW5gkd?~;F#2))xp=$(=Ddcku<=rs_ZM0}U@i$v%(5}|iV(wm8pze1dgxFYGT zM96!IkoOTE!?>4xWfXYS-$ulku@fIh9F_D?;ylDt;&`m@MA(ZU!k&W|jQyRYM@xDv z5q9x!LTLM@WFq`ZmGp^3*l`hI$4x~0cqBbb(q|H3Cr8rfO8R^v?Bx=Ju)Y&#A>I-p zUqqaZxJyJol@U>1IT7Wp6~0pV&B9j+zm50==C`Epl=K=R?C&8yivA~}UG@=Se?JlS zYl)CMLY$8N7ru@-AL~02dZ&rdJ41wCz3}IRZy@HN|A})Dza+m=@-GolPBRhha7Fm5 z#P1=V5>bwqh;n>Hlyj2^J^b!T)3Xu5+l9yf1B;d(Di}t52K_I5grGyv17!RxBx2q! zBVyjJBx2sy5HUaZ5;1R&2>%&z2iCt>AoTkYAsR8Zs8XbS7F`~QO*`3%6X9p zy;>sljuD}EM)+pItCDUTt;;!yC^wD>{TY(}C=vRLg4<-l9xCZ!!iNhVAw1v6rQR^%qlpFRU*Ykp zy_WwFkmD?$i2i+=i2f}hqJOK2=-(P5`ggzZ=ZNUv79#Yn5~1fMLT?D_LcL)`=;5UW zjn5)NFIV_N$zLh_9?3r@{7K1g5dNy*4I=CeN!0B+i7ZF>e8JU%eBa1gh;c+jyKW=G zMl})by;IU_h{1@X#1O;<;&_ZB$=^?eUM&%NM~IL=Ci!)ee^T;KOZpii`mbK{&q;oR zjD7+F^x@u`z-a;UrgKJo5d@Cs^isSF=lsG2%gInWAr7xP z=&Zt@dn_$j2GM29%L?M~g7IiP+F$gH5|=*f;kdlAvXUhWSCkc$V&MI29~?6j3n)Ou zaRgT`!Dr)RlP~uIQ7y$K{QNAm*--Qqc{Dg51m_C%{Ck90M?~=nX z)a)59(caWPNR$uDrOnBLev&?a67Cx1JHe>OG<>H#?ecR2as%|Q+F$08W(sPF_!Ghc zOdrbdlM6x}ius)%%9*Qd$Po?SDCdIQOf)E~@_i8f3k9)_jW)qorP`w?@0k(|dv|q{ N3wg%m1o8~I{|95i_D28! literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.d b/code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.d new file mode 100755 index 000000000..5b96a9334 --- /dev/null +++ b/code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.d @@ -0,0 +1,11 @@ +/home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../output/obj/4gMng/sf_eg91_sim.o /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../output/obj/4gMng/sf_eg91_sim.d : \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/src/sf_eg91_sim.c \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/logMng/inc/sf_log.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/commMng/inc/sf_type.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_common.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_enum.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_struct.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../hal/ttyusb/inc/sf_hal_ttyusb.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_opera_adapt.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_module.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_eg91_sim.h diff --git a/code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.o b/code/application/source/sf_app/output/obj/4gMng/sf_eg91_sim.o new file mode 100755 index 0000000000000000000000000000000000000000..28fd2a931275e180d2169c3208043d3cf7657e85 GIT binary patch literal 39184 zcmbWg3qVy>zCXSX=WsY6C>j|mslNvcv?#LPbCa-}uPLtRY|F zBjYw+#}s^!(=cl3lw)4AE|$N>>p1D{np%0A1CgE_ul_%uy}z5YIciP+Q{VGB-?i8J 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 Bp~e6J literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.d b/code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.d new file mode 100755 index 000000000..d23dece88 --- /dev/null +++ b/code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.d @@ -0,0 +1,9 @@ +/home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../output/obj/4gMng/sf_opera_adapt.o /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../output/obj/4gMng/sf_opera_adapt.d : \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/src/sf_opera_adapt.c \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/commMng/inc/sf_type.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/logMng/inc/sf_log.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_common.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_enum.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/paramMng/inc/sf_param_struct.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_opera_adapt.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/4gMng/../../component/4gMng/inc/sf_module.h diff --git a/code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.o b/code/application/source/sf_app/output/obj/4gMng/sf_opera_adapt.o new file mode 100755 index 0000000000000000000000000000000000000000..24c79d6a9a817b1567f11e2110964f3895aaa790 GIT binary patch literal 21244 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 ID9hCQKUh2l3jhEB literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/output/obj/dataMng/sf_data_proc.d b/code/application/source/sf_app/output/obj/dataMng/sf_data_proc.d new file mode 100755 index 000000000..07366613b --- /dev/null +++ b/code/application/source/sf_app/output/obj/dataMng/sf_data_proc.d @@ -0,0 +1,8 @@ +/home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../output/obj/dataMng/sf_data_proc.o /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../output/obj/dataMng/sf_data_proc.d : \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/src/sf_data_proc.c \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../component/dataMng/inc/sf_transdata1.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../component/commMng/inc/sf_type.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../component/paramMng/inc/sf_param_common.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../component/paramMng/inc/sf_param_enum.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../component/paramMng/inc/sf_param_struct.h \ + /home/lcy/caseclass/r7/T100/release/alkaid/sdk/verify/Cardvimpl/sf_cs/component/dataMng/../../component/dataMng/inc/sf_data_proc.h diff --git a/code/application/source/sf_app/output/obj/dataMng/sf_data_proc.o b/code/application/source/sf_app/output/obj/dataMng/sf_data_proc.o new file mode 100755 index 0000000000000000000000000000000000000000..f3abad1547d4716b6c13421ad636e20b7fd4044c GIT binary patch literal 3056 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 B-sAuP literal 0 HcmV?d00001 diff --git a/code/application/source/sf_app/sample/test/main.c b/code/application/source/sf_app/sample/test/main.c new file mode 100755 index 000000000..6941af378 --- /dev/null +++ b/code/application/source/sf_app/sample/test/main.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sf_type.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +SINT32 main(SINT32 s32Argc, SF_CHAR* pszArgv[]) +{ + + printf("*********************************************\n"); + printf("* *\n"); + printf("* sf_cs_app *\n"); + printf("* *\n"); + printf("*********************************************\n"); + + + + while(1) + { + usleep(1000 * 500); + } + + + exit(0); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + diff --git a/code/application/source/sf_app/sf_app b/code/application/source/sf_app/sf_app deleted file mode 100755 index 60b0a480fbb7788095709fd906e7141c67fd2de0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5132 zcmeHLPiP}$6n|eb-F9QToo=&k-HmQoB7}uZBSd!(JtSJi!!Fc%@?w~5rrSuHl*trY z5dYw%2Vn(0DvjW=V6Q?~A`}sCB6!`TbzrL%dQtG8@%Nj_w+&rk@!)M9{N}yyd%yR- z?|btF^5)%_Z@!|G5-l;w2}d8rloX+lOgs!3DN060;Y-PsoWT@*MKFmjY{D2I4xK`h z6!He(c;I7hB9w5{K>#rlOsc?tV?yM{L@dA&=Ep$gx{QwDS%SX=KheRMpr3nq&G%|h zkH{!yc$@|Jhx31jIfAj=(adtaIu>vKXSM}$68L#bK>J%aGp)M zN*?)d|28@C=MUX?I3AWOLxT+L>!-#~4UNyke&Wli09Hjf149aqwws9Dcmh?j7IH9~wJ1_m984 zd}ws@zR}(C&voy1$Bw`Dx5p9m?cIIz`w#cG|JwDn{l$>|>5%;iZD}7o)1T?dPWwQ* z?E}O7?C0@JyJuvOTk^iy+47A}-cQPwpDb+oNB#aUe!u_gc3jCO?7&1N35~Hypv`re;6;dd-t)I z^k6-lK9NHH4(3z==PB&@=6m-Z=(TsTXU#=f6U<>^FD7EXLX26u_uwa-kNeDFzvQzv zr|V9CBvA#T3Pcr%DiBp5sz6kMr~*+1q6+-~6w-{7UT3_%()!;diWYJydEhMYBEY+mLO=#K^WgJIpvRzJ02sr&$2(jE zkLze5pYj}_dEq?~nF~DOgFIpu&^-3$o5+{t#6WaD?o0Fdo7v_!2Tg+3yjKT2qzQWA zUGTJzbZsxdJ_oQi;kTm`AEp8xxo-kIKY9F3&SIc*VCo_7E!eCHdEvJvkq&IW4+>*g zKi({!gFNB)1ssCEb1mc%>wxB^!Apb3crAJl{6NHc<_o`BJerR&AB3D$+LSEvJs+CE SQZGKW8UCdGCt&%>fA-EHM3bDSaX^d7#moH7ai~ zBl9=3a4>FGsk_01EGW@fgQn;K3V%(9i~!7nb2E0a!PtHCx3MCdld#kQt`F$A&3jk0 VLmXye2=Zrh!rJW#YZ*6G0swevWl8`5 delta 314 zcmbPmj$;B4$*>t&7#W(IZd6*w!DeJ;YHDUW`Jb5h=C>T&d{F-8e`0L>$a0Em-7qoSpdOy({832P9~)!1ULp^ohXafktoE zsJy|9%-_($!MIta?gkUGphRO0nxY3N{52gi0x%2C&Dg~TWB1M9#)@oC!cqsgKA__^ a?_JT(!U_(P$%2&<&53KbC$42&UkLzr8f7&A diff --git a/code/hdal/vendor/output/libvendor_ai2_pub2.a b/code/hdal/vendor/output/libvendor_ai2_pub2.a index 953fe1d4e312523591430861005e4df97e1f4b2a..86fc95da4e29d6b14ba3b86d158e182c75cf1621 100755 GIT binary patch delta 393 zcmccjn(N+ct_d=1=7vTFCdM0;CI~{9hLa!2i*G(J$jt}kZ+;+ujvra>w0<{CZn8mu z_~v4}|C})SfKB3?`#ol}!}J;i@NvN8943ixj*d`<+Y_*CK(C93<5i9(PB1a zzW>VktS~;vFs}6uaKi#N&4W71c=CoeiDsVd+j+J#9;!sB7vKKcfJvPPB47kmB)(nW kmg%}0vI^xCrf6P-fY|m~g-k2NVOjzo zxyc3r;+u=@{&T|Q12&0o?)R9@4%2H8z{dfTbC@K)IXXfaZco6bvdzCTHCSNs59Gx* z+vQb=!1x>5#5Z4Vy3PzUYeU;N7#rwDvCW6NYGC}$8`|U;Hz)PqV1g-jm}DdXGYIUc zMT^;x`Ti^Cv%>fw!?@Nvzzqx7G!Nn^bA!nn+9aBJwr}Uz&UmO2p-Q<$Q85dvb{XB9H75Qk|A*d(z%p_8dj2LPd1d=3Br diff --git a/code/lib/source/sifar/Makefile b/code/lib/source/sifar/Makefile index a8a1bbdd8..3518d63c5 100755 --- a/code/lib/source/sifar/Makefile +++ b/code/lib/source/sifar/Makefile @@ -69,16 +69,18 @@ SRC = \ code/source/common/sf_common.c \ code/source/common/sf_led.c \ code/source/common/sf_battery.c \ - code/source/common/sf_message_queue.c \ - code/source/common/sf_share_mem.c \ - code/source/common/sf_base64.c \ - code/source/module/sf_tcp.c \ - code/source/module/sf_http.c \ - code/source/module/sf_4G_auto_operation.c \ - code/source/module/sf_4G_usb_uart.c \ - code/source/module/sf_sim.c \ - code/source/module/sf_hal_ttyusb.c \ - code/source/debug/sf_log.c \ + code/source/module/sf_tcp.c + +# code/source/common/sf_message_queue.c \ +# code/source/common/sf_share_mem.c \ +# code/source/common/sf_base64.c \ +# + # code/source/module/sf_http.c \ +# code/source/module/sf_4G_auto_operation.c \ +# code/source/module/sf_4G_usb_uart.c \ +# code/source/module/sf_sim.c \ +# code/source/module/sf_hal_ttyusb.c \ +# code/source/debug/sf_log.c \ OBJ = $(SRC:.c=.o) diff --git a/code/lib/source/sifar/code/include/sf_base64.h.bak b/code/lib/source/sifar/code/include/sf_base64.h.bak new file mode 100755 index 000000000..4e47737c2 --- /dev/null +++ b/code/lib/source/sifar/code/include/sf_base64.h.bak @@ -0,0 +1,25 @@ +#ifndef _SF_BASE64_H_ +#define _SF_BASE64_H_ +#include "sf_type.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#if 0 +int sf_base64_decode(const char * base64, char * bindata); + +char * sf_base64_encode(const char * bindata, char * base64, int binlength, int model); + +int URLEncode(const char* str, const int strSize, char* result, const int resultSize); + +#endif +#ifdef __cplusplus +#if __cplusplus + } +#endif +#endif + +#endif + diff --git a/code/lib/source/sifar/code/include/sf_battery.h b/code/lib/source/sifar/code/include/sf_battery.h index 57ec276e3..89beca0fe 100755 --- a/code/lib/source/sifar/code/include/sf_battery.h +++ b/code/lib/source/sifar/code/include/sf_battery.h @@ -2,7 +2,7 @@ #define _SF_BATTERY_ #include -#include +//#include //typedef signed int SINT32; @@ -13,7 +13,7 @@ UINT32 sf_adc_value_get(UINT32 mux, UINT32 *pval); UINT32 sf_battery_adc_value_get_once(void); void sf_battery_level_update(void); BOOL sf_check_low_battery(void); -SINT32 sf_battery_adc_value_get(void); +signed int sf_battery_adc_value_get(void); void sf_battery_level_polling(void); THREAD_RETTYPE sf_battery_check_thread(void *arg); void sf_battery_thread_init(void); diff --git a/code/lib/source/sifar/code/include/sf_hal_ttyusb.h b/code/lib/source/sifar/code/include/sf_hal_ttyusb.h.bak similarity index 95% rename from code/lib/source/sifar/code/include/sf_hal_ttyusb.h rename to code/lib/source/sifar/code/include/sf_hal_ttyusb.h.bak index 9bffa5848..66aa5831d 100755 --- a/code/lib/source/sifar/code/include/sf_hal_ttyusb.h +++ b/code/lib/source/sifar/code/include/sf_hal_ttyusb.h.bak @@ -26,6 +26,7 @@ extern "C" { #endif #include +#if 0 #define SF_TTY_ERROR_OPEN SF_ERR_ID(SF_MOD_TTY, ERROR_AT_OPEN) #define SF_TTY_ERROR_WRITE SF_ERR_ID(SF_MOD_TTY, ERROR_AT_WRITE) @@ -77,7 +78,7 @@ SINT32 sf_hal_uart_read(SF_CHAR *recvBuf, SINT32 dataLen); SINT32 sf_hal_uart_deinit(void); - +#endif #ifdef __cplusplus #if __cplusplus diff --git a/code/lib/source/sifar/code/include/sf_inc.h b/code/lib/source/sifar/code/include/sf_inc.h index 11504b276..d32124c81 100755 --- a/code/lib/source/sifar/code/include/sf_inc.h +++ b/code/lib/source/sifar/code/include/sf_inc.h @@ -12,11 +12,11 @@ #include #include #include -#include -#include -#include -#include -#include +//#include +//#include +//#include +//#include +//#include #endif diff --git a/code/lib/source/sifar/code/include/sf_log.h b/code/lib/source/sifar/code/include/sf_log.h.bak similarity index 96% rename from code/lib/source/sifar/code/include/sf_log.h rename to code/lib/source/sifar/code/include/sf_log.h.bak index 6b944040e..0376e5326 100755 --- a/code/lib/source/sifar/code/include/sf_log.h +++ b/code/lib/source/sifar/code/include/sf_log.h.bak @@ -36,6 +36,9 @@ extern "C" { #endif #endif + +#if 0 + #define LOG_TMP_MOD_FILE_PATH SF_SD_ROOT"SF_GPS.TXT" #define LOG_AT_FILE_PATH SF_SD_ROOT"SF_GPS.TXT" #define WARNING_FILE_PATH SF_SD_ROOT"warning.txt" @@ -102,7 +105,7 @@ void sf_log_module(const char *pszFunc, U32 u32Line, const char *pszFmt, ...); void sf_log_file(SF_LOG_LEVEL_e enLevel,const char *pszFunc, U32 u32Line,char *pszFmt, ...); - +#endif #ifdef __cplusplus #if __cplusplus diff --git a/code/lib/source/sifar/code/include/sf_mcu.h b/code/lib/source/sifar/code/include/sf_mcu.h index 4f8e32adf..ce93f9dd8 100755 --- a/code/lib/source/sifar/code/include/sf_mcu.h +++ b/code/lib/source/sifar/code/include/sf_mcu.h @@ -418,6 +418,8 @@ int sf_while_flag(void); UINT8 sf_mcu_power_on_para_get(MCUParam_t attrId); void sf_set_sim_insert(UINT8 sim); UINT8 sf_get_mcu_rtc_set_sys(void); +unsigned short sf_get_mcu_ver(void); +UINT16 sf_mcu_get_irshtter(void); #endif diff --git a/code/lib/source/sifar/code/include/sf_message_queue.h b/code/lib/source/sifar/code/include/sf_message_queue.h.bak similarity index 93% rename from code/lib/source/sifar/code/include/sf_message_queue.h rename to code/lib/source/sifar/code/include/sf_message_queue.h.bak index 8bd5dc9c2..727c2db16 100755 --- a/code/lib/source/sifar/code/include/sf_message_queue.h +++ b/code/lib/source/sifar/code/include/sf_message_queue.h.bak @@ -8,6 +8,7 @@ extern "C" { #include #include "UIInfo/UIInfo.h" +#if 0 typedef struct sf_MESSAGE_Buf_S { long mtype; @@ -27,6 +28,8 @@ SINT32 sf_com_message_cardv_init(void); SINT32 sf_com_message_send_to_cardv(SF_MESSAGE_BUF_S *pMessageBuf); SINT32 sf_com_message_recv_from_cardv(SF_MESSAGE_BUF_S *pMessageBuf); +#endif + #ifdef __cplusplus #if __cplusplus } diff --git a/code/lib/source/sifar/code/include/sf_share_mem.h b/code/lib/source/sifar/code/include/sf_share_mem.h.bak similarity index 94% rename from code/lib/source/sifar/code/include/sf_share_mem.h rename to code/lib/source/sifar/code/include/sf_share_mem.h.bak index cfbfc47d4..01280a0f1 100755 --- a/code/lib/source/sifar/code/include/sf_share_mem.h +++ b/code/lib/source/sifar/code/include/sf_share_mem.h.bak @@ -7,6 +7,7 @@ extern "C" { #endif #include "sf_type.h" +#if 0 #define SF_MAX_PATH_LEN 128 #define SF_MAX_PIC_LEN 64 #define SF_SRCFILE_MAX 4 @@ -76,7 +77,7 @@ SINT32 sf_share_mem_customer_init(void); SINT32 sf_share_mem_customer_deinit(void); - +#endif #ifdef __cplusplus #if __cplusplus diff --git a/code/lib/source/sifar/code/include/sf_sim.h b/code/lib/source/sifar/code/include/sf_sim.h index 4e5ae2c92..a3fc116e9 100755 --- a/code/lib/source/sifar/code/include/sf_sim.h +++ b/code/lib/source/sifar/code/include/sf_sim.h @@ -1,6 +1,5 @@ #ifndef _SF_SIM_ #define _SF_SIM_ -#include #ifdef __cplusplus #if __cplusplus @@ -8,6 +7,9 @@ extern "C" { #endif #endif +#if 0 +#include + #define sf_4g_send_data sf_hal_ttyusb2_write #define sf_4g_get_data sf_hal_ttyusb2_read @@ -38,7 +40,6 @@ extern "C" { * error_code : error code in specified module, unique in module **/ #define SF_ERR_ID(module, err) ((SINT32)(((module) << 16) | (err))) - typedef enum SF_SIM { SMS_SIM_INIT_READY= (unsigned char)0x01, @@ -287,6 +288,8 @@ typedef enum _UPLOAD_ERR_CODE_E{ UINT32 sf_auto_operation_adjust(void); +#endif + #ifdef __cplusplus #if __cplusplus } diff --git a/code/lib/source/sifar/code/include/sf_type.h b/code/lib/source/sifar/code/include/sf_type.h.bak similarity index 93% rename from code/lib/source/sifar/code/include/sf_type.h rename to code/lib/source/sifar/code/include/sf_type.h.bak index 46094abd3..026ed8660 100755 --- a/code/lib/source/sifar/code/include/sf_type.h +++ b/code/lib/source/sifar/code/include/sf_type.h.bak @@ -1,6 +1,8 @@ #ifndef _SF_TYPE_H_ #define _SF_TYPE_H_ +#if 1 + #ifndef SF_DATA_TYPE #define SF_DATA_TYPE @@ -49,4 +51,7 @@ typedef void SF_VOID; #define SF_TRUE 1 #define SF_FALSE 0 #endif + +#endif + #endif \ No newline at end of file diff --git a/code/lib/source/sifar/code/source/common/sf_base64.c.bak b/code/lib/source/sifar/code/source/common/sf_base64.c.bak new file mode 100755 index 000000000..d02bbe331 --- /dev/null +++ b/code/lib/source/sifar/code/source/common/sf_base64.c.bak @@ -0,0 +1,145 @@ + +#include +#include +#include + +#include "sf_type.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +static char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +int sf_base64_decode(const char * base64, char * bindata) +{ + int i, j; + U8 k; + U8 temp[4]; + for (i = 0, j = 0; base64[i] != '\0'; i += 4) + { + memset(temp, 0xFF, sizeof(temp)); + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i]) + temp[0] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 1]) + temp[1] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 2]) + temp[2] = k; + } + for (k = 0; k < 64; k++) + { + if (base64char[k] == base64[i + 3]) + temp[3] = k; + } + + bindata[j++] = ((U8)(((U8)(temp[0] << 2)) & 0xFC)) | + ((U8)((U8)(temp[1] >> 4) & 0x03)); + if (base64[i + 2] == '=') + break; + + bindata[j++] = ((U8)(((U8)(temp[1] << 4)) & 0xF0)) | + ((U8)((U8)(temp[2] >> 2) & 0x0F)); + if (base64[i + 3] == '=') + break; + + bindata[j++] = ((U8)(((U8)(temp[2] << 6)) & 0xF0)) | + ((U8)(temp[3] & 0x3F)); + } + return j; +} + +char * sf_base64_encode(const char * bindata, char * base64, int binlength, int model) +{ + int i, j; + unsigned char current; + + for (i = 0, j = 0; i < binlength; i += 3) + { + current = (bindata[i] >> 2); + current &= (unsigned char)0x3F; + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30); + if (i + 1 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C); + if (i + 2 >= binlength) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + break; + } + current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03); + base64[j++] = base64char[(int)current]; + + current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F); + base64[j++] = base64char[(int)current]; + } + if(model) + { + base64[j++] = '\n'; + } + base64[j] = '\0'; + return base64; +} +int URLEncode(const char* str, const int strSize, char* result, const int resultSize) +{ + int i; + int j = 0;//for result index + char ch; + + if ((str == 0) || (result == 0) || (strSize <= 0) || (resultSize <= 0)) { + return 0; + } + + for (i = 0; (i= 'A') && (ch<='Z')) || + ((ch >= 'a') && (ch<='z')) || + ((ch >= '0') && (ch<='9'))) { + result[j++] = ch; + } + else if (ch == ' ') { + result[j++] = '+'; + } + else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') { + result[j++] = ch; + } + else { + if (j + 3 < resultSize) { + sprintf(result + j, "%%%02X", (unsigned char)ch); + j += 3; + } + else { + return 0; + } + } + } + + result[j] = '\0'; + return j; +} + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + diff --git a/code/lib/source/sifar/code/source/common/sf_battery.c b/code/lib/source/sifar/code/source/common/sf_battery.c index 33ede99ff..88c0754bf 100755 --- a/code/lib/source/sifar/code/source/common/sf_battery.c +++ b/code/lib/source/sifar/code/source/common/sf_battery.c @@ -44,6 +44,7 @@ #include "IOCfg.h" #if HUNTING_CAMERA_MCU == ENABLE +typedef signed int SINT32; UINT32 _DcVoltageVal = 0; UINT32 _LiPolymerVoltageVal = 0; /*4.0P no use*/ @@ -420,7 +421,7 @@ BOOL sf_check_low_battery(void) Return: SUCCESS/FAIL Others: N/A *******************************************************/ -SINT32 sf_battery_adc_value_get(void) +signed int sf_battery_adc_value_get(void) { UINT8 readBatCnt = 0; diff --git a/code/lib/source/sifar/code/source/common/sf_common.c b/code/lib/source/sifar/code/source/common/sf_common.c index 48cbacf30..5fd5fedc2 100755 --- a/code/lib/source/sifar/code/source/common/sf_common.c +++ b/code/lib/source/sifar/code/source/common/sf_common.c @@ -474,6 +474,8 @@ BOOL sf_cmd_work_time_switch(unsigned char argc, char **argv) puiPara->WorkTime[0].StopTime.Hour = value; sscanf_s(argv[5],"%d", &value); puiPara->WorkTime[0].StopTime.Min = value; + + Save_MenuInfo(); } printf("[%s:%d] argc:%d WorkTime1Switch:%d %d:%d-%d:%d\n", __FUNCTION__, __LINE__, argc, SysGetFlag(WorkTime1Switch),puiPara->WorkTime[0].StartTime.Hour,puiPara->WorkTime[0].StartTime.Min,puiPara->WorkTime[0].StopTime.Hour,puiPara->WorkTime[0].StopTime.Min); } @@ -491,6 +493,7 @@ BOOL sf_cmd_work_time_switch(unsigned char argc, char **argv) puiPara->WorkTime[1].StopTime.Hour = value; sscanf_s(argv[5],"%d", &value); puiPara->WorkTime[1].StopTime.Min = value; + Save_MenuInfo(); } printf("[%s:%d] argc:%d WorkTime1Switch:%d %d:%d-%d:%d\n", __FUNCTION__, __LINE__, argc, SysGetFlag(WorkTime2Switch),puiPara->WorkTime[1].StartTime.Hour,puiPara->WorkTime[1].StartTime.Min,puiPara->WorkTime[1].StopTime.Hour,puiPara->WorkTime[1].StopTime.Min); @@ -902,7 +905,7 @@ BOOL cmd_cam_mode(unsigned char argc, char **argv) UINT32 value; sscanf_s(argv[0],"%d", &value); if(value < SF_CAM_MODE_MAX){ - SysSetFlag(CamMode, SF_CAM_MODE_PHOTO_VIDEO); + SysSetFlag(CamMode, value); Save_MenuInfo(); } printf("[%s:%d] CamMode:%d\n", __FUNCTION__, __LINE__,SysGetFlag(CamMode)); diff --git a/code/lib/source/sifar/code/source/common/sf_message_queue.c b/code/lib/source/sifar/code/source/common/sf_message_queue.c.bak similarity index 98% rename from code/lib/source/sifar/code/source/common/sf_message_queue.c rename to code/lib/source/sifar/code/source/common/sf_message_queue.c.bak index 71f888a93..76045419c 100755 --- a/code/lib/source/sifar/code/source/common/sf_message_queue.c +++ b/code/lib/source/sifar/code/source/common/sf_message_queue.c.bak @@ -88,7 +88,7 @@ SINT32 sf_com_message_send_to_app(SF_MESSAGE_BUF_S *pMessageBuf) return message_queue_send(sf_msgQueueId,pMessageBuf); } -SINT32 sf_com_message_cardv_init() +SINT32 sf_com_message_cardv_init(void) { return message_queue_create((char*)"/tmp/cardv_message",&cardv_msgQueueId); } diff --git a/code/lib/source/sifar/code/source/common/sf_share_mem.c b/code/lib/source/sifar/code/source/common/sf_share_mem.c.bak similarity index 100% rename from code/lib/source/sifar/code/source/common/sf_share_mem.c rename to code/lib/source/sifar/code/source/common/sf_share_mem.c.bak diff --git a/code/lib/source/sifar/code/source/debug/sf_log.c b/code/lib/source/sifar/code/source/debug/sf_log.c.bak similarity index 100% rename from code/lib/source/sifar/code/source/debug/sf_log.c rename to code/lib/source/sifar/code/source/debug/sf_log.c.bak diff --git a/code/lib/source/sifar/code/source/mcu/sf_mcu_client.c b/code/lib/source/sifar/code/source/mcu/sf_mcu_client.c index 600871336..1226d9450 100755 --- a/code/lib/source/sifar/code/source/mcu/sf_mcu_client.c +++ b/code/lib/source/sifar/code/source/mcu/sf_mcu_client.c @@ -1647,6 +1647,37 @@ UINT8 sf_mcu_reg_set(MCUParam_t attrId, UINT8 val) mcuReg[i] = WORKTIME1_STOP_MINUTE; mcuData[i++] = 0; } + + if(SysGetFlag(WorkTime2Switch)) + { + mcuReg[i] = WORKTIME2_SWITCH; + mcuData[i++] = 0xFF; + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = puiPara->WorkTime[1].StartTime.Hour; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = puiPara->WorkTime[1].StartTime.Min; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = puiPara->WorkTime[1].StopTime.Hour; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = puiPara->WorkTime[1].StopTime.Min; + } + else + { + mcuReg[i] = WORKTIME2_SWITCH; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = 0; + } if((SysGetFlag(GpsSwitch) || SysGetFlag(FristSendDailyAndGps)) && (sf_get_mode_flag() || paraSyncFlag)) { @@ -1970,4 +2001,46 @@ void sf_set_sim_insert(UINT8 sim) simCardInsert = sim; } +unsigned short sf_get_mcu_ver(void) +{ + return McuVersion; +} + + +/************************************************* + Function: sf_mcu_get_irshtter + Description: get IRSHTTER. + Input: N/A + Output: N/A + Return: IRSHTTER + Others: N/A +*************************************************/ +UINT16 sf_mcu_get_irshtter(void) +{ + UINT8 dataTemp1 = 0, dataTemp2 = 0; + + #if HUNTING_MCU_I2C == ENABLE + sf_mcu_read(LUMINANCE_L, &dataTemp1); + sf_mcu_read(LUMINANCE_H, &dataTemp2); + #else + UINT8 mcuReg[REG_SIZE] = { 0 }; + UINT8 mcuData[REG_SIZE] = { 0 }; + UINT8 i = 0; + + mcuReg[i++] = LUMINANCE_L; + mcuReg[i++] = LUMINANCE_H; + sf_mcu_read_multi(mcuReg, mcuData, i); + i = 0; + + dataTemp1= mcuData[i++]; + dataTemp2 = mcuData[i++]; + #endif + + IRSHTTER = (dataTemp2 << 8) | dataTemp1; + + printf("IRSHTTER = %d\n", IRSHTTER); + + return IRSHTTER; +} + diff --git a/code/lib/source/sifar/code/source/module/sf_hal_ttyusb.c b/code/lib/source/sifar/code/source/module/sf_hal_ttyusb.c.bak similarity index 100% rename from code/lib/source/sifar/code/source/module/sf_hal_ttyusb.c rename to code/lib/source/sifar/code/source/module/sf_hal_ttyusb.c.bak diff --git a/configs/Linux/cfg_565_HUNTING_EVB_LINUX_4G_S530/nvt-info.dtsi b/configs/Linux/cfg_565_HUNTING_EVB_LINUX_4G_S530/nvt-info.dtsi index c966d5cd9..04d9cf59e 100755 --- a/configs/Linux/cfg_565_HUNTING_EVB_LINUX_4G_S530/nvt-info.dtsi +++ b/configs/Linux/cfg_565_HUNTING_EVB_LINUX_4G_S530/nvt-info.dtsi @@ -45,7 +45,7 @@ */ NVT_CFG_APP_EXTERNAL = "hostapd wireless_tool iperf-3 wpa_supplicant dhd_priv"; /* application include list */ - NVT_CFG_APP = "mem cardv memcpy isp_demon"; + NVT_CFG_APP = "mem cardv memcpy isp_demon sf_app"; /* rootfs etc folder */ NVT_ROOTFS_ETC = ""; /* strip executable binary and library files: yes/no */ diff --git a/rtos/code/application/source/cardv/SrcCode/FastFlow/flow_preview.c b/rtos/code/application/source/cardv/SrcCode/FastFlow/flow_preview.c index b7778735e..32b2d1eb3 100755 --- a/rtos/code/application/source/cardv/SrcCode/FastFlow/flow_preview.c +++ b/rtos/code/application/source/cardv/SrcCode/FastFlow/flow_preview.c @@ -152,16 +152,6 @@ static HD_RESULT flowpreview_mem_relayout(void) #if POWERON_FAST_SLICE_ENC == ENABLE - { - PhotoFast_SliceSize_Info dst_slice_info; - PhotoFast_SliceEncode_Get_Curr_Dst_Slice_Info(&dst_slice_info); - - mem_cfg.pool_info[2].type = HD_COMMON_MEM_COMMON_POOL; - mem_cfg.pool_info[2].blk_size = DBGINFO_BUFSIZE() + PhotoFast_SliceEncode_Get_Max_Dst_Slice_Buffer_Size(HD_VIDEO_PXLFMT_YUV420); - mem_cfg.pool_info[2].blk_cnt = 1; - mem_cfg.pool_info[2].ddr_id = DDR_ID0; - } - #else // config common pool (primary image) @@ -252,7 +242,13 @@ static HD_RESULT set_cap_param(HD_PATH_ID video_cap_path, HD_DIM *p_dim) UIAPP_PHOTO_SENSOR_INFO *pSensorInfo = UIAppPhoto_get_SensorInfo(0); video_in_param.sen_mode = HD_VIDEOCAP_PATGEN_MODE(1, ALIGN_CEIL((pSensorInfo->sSize.w *10/65), 2)); #endif + +#if HUNTING_PHOTO_FAST_AE_60_FPS == ENABLE + video_in_param.frc = HD_VIDEO_FRC_RATIO(60,1); +#else video_in_param.frc = HD_VIDEO_FRC_RATIO(30,1); +#endif + video_in_param.dim.w = p_dim->w; video_in_param.dim.h = p_dim->h; video_in_param.pxlfmt = SEN_OUT_FMT; @@ -304,6 +300,14 @@ static HD_RESULT set_cap_param(HD_PATH_ID video_cap_path, HD_DIM *p_dim) video_out_param.pxlfmt = CAP_OUT_FMT; } video_out_param.dir = HD_VIDEO_DIR_NONE; + video_out_param.frc = 0; + +#if HUNTING_PHOTO_FAST_AE_60_FPS == ENABLE + video_out_param.depth = 1; +#else + video_out_param.depth = 0; +#endif + ret = hd_videocap_set(video_cap_path, HD_VIDEOCAP_PARAM_OUT, &video_out_param); //printf("set_cap_param OUT=%d\r\n", ret); } @@ -393,6 +397,19 @@ static HD_RESULT set_proc_param(HD_PATH_ID video_proc_path, HD_DIM* p_dim) ret = hd_videoproc_set(video_proc_path, HD_VIDEOPROC_PARAM_OUT, &video_out_param); } +#if HUNTING_PHOTO_FAST_AE_60_FPS == ENABLE + { + HD_VIDEOPROC_IN video_in_param = {0}; + video_in_param.func = 0; + video_in_param.dim.w = p_dim->w; + video_in_param.dim.h = p_dim->h; + video_in_param.pxlfmt = HD_VIDEO_PXLFMT_RAW12; + video_in_param.dir = HD_VIDEO_DIR_NONE; + video_in_param.frc = HD_VIDEO_FRC_RATIO(1, 1); + ret = hd_videoproc_set(video_proc_path, HD_VIDEOPROC_PARAM_IN, &video_in_param); + } +#endif + return ret; } @@ -688,7 +705,10 @@ static THREAD_RETTYPE thread_cap_proc(void *ptr) } // bind video_liveview modules (main) +#if HUNTING_PHOTO_FAST_AE_60_FPS == ENABLE +#else hd_videocap_bind(HD_VIDEOCAP_0_OUT_0, HD_VIDEOPROC_0_IN_0); +#endif // start video_liveview modules (main) hd_videocap_start(stream[0].cap_path); @@ -772,6 +792,7 @@ void flow_preview_get_path(HD_PATH_ID *pPath, FLOW_PREIVEW_PATH PathType, UINT32 { switch (PathType) { case FLOW_PREIVEW_VCAP_PATH: + *pPath = stream[0].cap_path; break; case FLOW_PREIVEW_VPRC_PATH: @@ -1024,64 +1045,65 @@ void flow_preview_uninit_module(void) static UINT32 ae_adc_tbl[57][3] = { -#if 0 //for 200K RSS photodie - {980, 120, 1000}, - {970, 250, 1000},//{970, 300, 1000}, - {960, 300, 1000},//{960, 500, 1000}, - {945, 400, 1000}, - {930, 500, 1000}, - {910, 600, 1000}, - {900, 700, 1000}, - {885, 800, 1000}, - {870, 1000, 1000},//{870, 2000, 1000}, - {850, 1200, 1000}, - {840, 2700, 1000}, - {832, 4201, 1000}, - {820, 5801, 1000}, - {816, 7332, 1000}, - {810, 8333, 1000}, - {805, 8333, 1000}, - {800, 8333, 1000}, - {787, 25000, 1000}, - {750, 25000, 1000}, - {723, 25000, 1000}, - {671, 33333, 1000}, - {641, 33333, 1000}, - {600, 16666, 1000},// night - {538, 16666, 1000}, - {503, 16666, 1000}, - {484, 16666, 1000}, - {466, 16666, 1500}, - {414, 16666, 1500}, - {368, 16666, 1500}, - {313, 16666, 2000}, - {257, 25000, 2000}, - {218, 16666, 2000}, - {185, 16666, 2000},//6890 - {165, 16666, 2000}, - {143, 16666, 2000},//6610 - {124, 16666, 2000},//7280 - {109, 16666, 2000},//8130 - {84, 16666, 2000},//10260 - {76, 16666, 2000}, - {60, 16666, 2000}, - {49, 25000, 2000}, - {36, 25000, 2000},//25070 - {31, 25000, 2000}, - {26, 25000, 2000},//33740}, - {19, 25000, 2000},//45740}, - {17, 25000, 2000},//48740}, - {15, 25000, 2000},//54740}, - {13, 25000, 2000},//58740}, - {12, 33333, 2000},//61040}, - {11, 33333, 2000},//68040}, - {10, 33333, 2000},//69920},// - {9, 33333, 2000},//74920}, - {8, 33333, 2000},//77740}, - {6, 33333, 2000},//83740}, - {5, 33333, 2000},//10740}, - {2, 33333, 2000},//128000}, - {0, 33333, 6000},//128000}, +#if 1 //for S530 200K RSS photodie + {980, 44, 1000}, + {970, 73, 1000}, + {960, 88, 1000}, + {945, 99, 1130}, + {930, 103, 1000}, + {910, 126, 1070}, + {900, 135, 1020}, + {885, 153, 1040}, + {870, 160, 1090}, + {859, 177, 1010}, + {854, 258, 1000}, + {849, 500, 1000}, + {845, 768, 1000}, + {842, 984, 1000}, + {839, 1372, 1000}, + {830, 2236, 1000}, + {828, 3459, 1000}, + {824, 5213, 1000}, + {822, 7232, 1000}, + {813, 8333, 1280}, + {809, 8333, 2380}, + {799, 16666, 4300}, + {787, 16666, 6390}, + {735, 16666, 7990}, + {686, 16666, 8460}, + {652, 16666, 9530}, + {613, 16666, 10690}, + {576, 16666, 2310},//night + {541, 16666, 2310}, + {509, 16666, 2310}, + {480, 16666, 2310}, + {458, 16666, 2310}, + {421, 16666, 2310}, + {399, 16666, 2310}, + {363, 16666, 2310}, + {322, 16666, 2310},// 12190}, + {288, 16666, 2310},// 26600}, + {246, 16666, 2310}, //45770}, + {216, 16666, 2310}, + {188, 16666, 1000}, + {162, 16666, 1000}, + {151, 16666, 1000}, + {138, 16666, 1000}, + {118, 16666, 1000}, + {96, 16666, 1280}, + {80, 16666, 2000}, + {62, 16666, 2000}, + {48, 20000, 2000}, + {35, 20000, 2000}, + {26, 33333, 1100}, + {19, 33333, 1100}, + {13, 33333, 1100}, + {10, 33333, 1100}, + {8, 33333, 2100}, + {4, 33333, 3100}, + {2, 33333, 3000}, + {0, 33333, 4000}, + #else // 1K RSS {980, 120, 1000}, {970, 120, 1000}, @@ -1135,10 +1157,10 @@ static UINT32 ae_adc_tbl[57][3] = { {11, 8333, 1000}, {10, 8333, 1000}, {9, 8333, 1000}, - {8, 16666, 1000}, - {6, 16666, 2000}, - {5, 16666, 2000}, - {2, 33333, 2000}, + {8, 8333, 1000}, + {6, 8333, 1000}, + {5, 8333, 1000}, + {1, 16666, 1000}, {0, 33333, 4000}, #endif }; @@ -1180,6 +1202,7 @@ void ae_adc_get_exp_photo(UINT16 adc_value, UINT32 *exptime, UINT32 *isogain) } +UINT32 ae_preset_exp,ae_preset_iso; void get_preset_param(void) { @@ -1189,8 +1212,8 @@ void get_preset_param(void) if(get_preset_flag==FALSE) { ae_adc_get_exp_photo(IRSHTTER, &adc_expt, &adc_gain); - preset_param.expt= adc_expt; - preset_param.gain= adc_gain; + preset_param.expt= ae_preset_exp = adc_expt; + preset_param.gain= ae_preset_iso = adc_gain; DBG_WRN("adc_value = %d, adc_exp =========== %d, %d\r\n", IRSHTTER, (unsigned int)adc_expt, (unsigned int)adc_gain); get_preset_flag=TRUE; @@ -1200,12 +1223,16 @@ void get_preset_param(void) void setet_preset_param(void) { AET_STATUS_INFO ae_status_info = {0}; + ISPT_TOTAL_GAIN total_gain = {0}; ae_status_info.id = 0; vendor_isp_get_ae(AET_ITEM_STATUS, &ae_status_info); DBG_WRN(">> aet status exp %d iso %d\r\n",ae_status_info.status_info.expotime[0],ae_status_info.status_info.iso_gain[0]); preset_param.expt= ae_status_info.status_info.expotime[0]; preset_param.gain= ae_status_info.status_info.iso_gain[0]; + total_gain.id = 0; + total_gain.gain = preset_param.gain/5; + vendor_isp_set_common(ISPT_ITEM_TOTAL_GAIN, &total_gain); } diff --git a/rtos/code/application/source/cardv/SrcCode/PrjCfg_Default.h b/rtos/code/application/source/cardv/SrcCode/PrjCfg_Default.h index 617075f2a..c603847a4 100755 --- a/rtos/code/application/source/cardv/SrcCode/PrjCfg_Default.h +++ b/rtos/code/application/source/cardv/SrcCode/PrjCfg_Default.h @@ -252,4 +252,8 @@ #define DCF_FILE_NAME "IMAG" /* IMAG0001.JPG */ #endif +#ifndef HUNTING_PHOTO_FAST_AE_60_FPS +#define HUNTING_PHOTO_FAST_AE_60_FPS DISABLE +#endif + #endif //_PRJCFG_DEFAULT_H_ diff --git a/rtos/code/application/source/cardv/SrcCode/PrjCfg_HUNTING_S530.h b/rtos/code/application/source/cardv/SrcCode/PrjCfg_HUNTING_S530.h index c9a5180b3..694d85fcb 100755 --- a/rtos/code/application/source/cardv/SrcCode/PrjCfg_HUNTING_S530.h +++ b/rtos/code/application/source/cardv/SrcCode/PrjCfg_HUNTING_S530.h @@ -949,6 +949,7 @@ #define HUNTING_IR_LED_940 DISABLE #define SF_EXIF_MN_BUF_SIZE 256 #define SF_BASE_VERSION "7MD4RCwD3T2" +#define HUNTING_PHOTO_FAST_AE_60_FPS ENABLE /******************************************************************************************* * LVGL UI Style config diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/MovieFast/MovieFast.c b/rtos/code/application/source/cardv/SrcCode/UIApp/MovieFast/MovieFast.c index 477a7da8e..beb1843f8 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/MovieFast/MovieFast.c +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/MovieFast/MovieFast.c @@ -457,6 +457,7 @@ static void MovieFast_OnRecStart(void) #if defined(_UI_STYLE_LVGL_) flow_lv_init(); #endif + vos_util_delay_ms(99); movie_rec_mask = Movie_GetMovieRecMask(); clone_rec_mask = Movie_GetCloneRecMask(); @@ -702,6 +703,7 @@ THREAD_RETTYPE MovieFast_InitFileNamingThread(void *arg) } extern void Set_NIGHTMODE(UINT32 id, UINT8 isSnapVideo); extern void Set_AEMODE(UINT32 id); +extern void setet_preset_param(void); THREAD_RETTYPE MovieFast_InitMovieModeThread(void *arg) { UINT32 i; @@ -796,13 +798,17 @@ THREAD_RETTYPE MovieFast_InitMovieModeThread(void *arg) ImageApp_MovieMulti_SetParam(_CFG_REC_ID_1, MOVIEMULTI_PARAM_FILE_USE_FILEDB, FALSE); ImageApp_MovieMulti_SetParam(_CFG_REC_ID_1, MOVIEMULTI_PARAM_FILE_CB_CLOSED_FILE_INFO, TRUE); - + setet_preset_param(); ImageApp_MovieMulti_Open(); for (i = 0; i < SENSOR_CAPS_COUNT; i++) { ImageApp_MovieMulti_SetParam(_CFG_REC_ID_1 + i, MOVIEMULTI_PARAM_FILE_FRONT_MOOV, TRUE); ImageApp_MovieMulti_SetParam(_CFG_REC_ID_1 + i, MOVIEMULTI_PARAM_FILE_FRONT_MOOV_FLUSH_SEC, 2); } + + if (1){//gMovie_Alg_Info[_CFG_REC_ID_1 + i].path13.ImgSize.w && gMovie_Alg_Info[_CFG_REC_ID_1 + i].path13.ImgSize.h) { + ImageApp_MovieMulti_ImgLinkForAlg((_CFG_REC_ID_1 ), _CFG_ALG_PATH3, ENABLE, TRUE); + } #if (_PACKAGE_DISPLAY_) ImageApp_MovieMulti_ImgLinkForDisp(_CFG_REC_ID_1, DISABLE, TRUE); @@ -818,8 +824,8 @@ THREAD_RETTYPE MovieFast_InitMovieModeThread(void *arg) MovieFast_InstallID(); vos_util_delay_ms(500); - Set_AEMODE(1); - vos_util_delay_ms(500); + //Set_AEMODE(1); + //vos_util_delay_ms(500); if ((g_moviefast_tsk_id = vos_task_create(MovieFast_CmdTsk, 0, "MovieFastTsk", PRI_MOVIEFAST_CMDTSK, STKSIZE_MOVIEFAST_CMDTSK)) == 0) { DBG_ERR("MovieFastTsk create failed.\r\n"); diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c b/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c index 998867f7f..11093feab 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.c @@ -22,6 +22,7 @@ #if MOVIE_ISP_LOG #include "vendor_isp.h" +#include "sf_mcu.h" #endif //#NT#2016/10/17#Bin Xiao -end #define __MODULE__ MovieStamp @@ -277,13 +278,17 @@ ISIZE MovieStamp_GetStampDataWidth(PSTAMP_INFO pStampInfo, const IMAGE_TABLE *pT #endif #if MOVIE_ISP_LOG +//extern UINT8 sf_mcu_power_on_para_get(MCUParam_t attrId); +//extern UINT16 IRSHTTER; static void MovieStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) { AET_STATUS_INFO ae_status = {0}; AWBT_STATUS awb_status = {0}; IQT_WDR_PARAM wdr = {0}; //IQT_DEFOG_PARAM defog = {0}; -id = 0; + //sf_mcu_power_on_para_get(SF_MCU_POWERON); + + id = 0; ae_status.id = id; vendor_isp_get_ae(AET_ITEM_STATUS, &ae_status); awb_status.id = id; @@ -292,7 +297,8 @@ id = 0; vendor_isp_get_iq(IQT_ITEM_WDR_PARAM, &wdr); //defog.id = id; //vendor_isp_get_iq(IQT_ITEM_DEFOG_PARAM, &defog); - snprintf(Buf, BufLen, "%3d %4d %4d %6d %6d %4d %4d %d %4d %4d %4d\0", + snprintf(Buf, BufLen, "%d %3d %3d %3d %6d %6d %3d %3d %d %3d %3d %4d\0", + ae_status.status_info.state_adj, ae_status.status_info.lv/100000, ae_status.status_info.lum, ae_status.status_info.expect_lum, @@ -305,6 +311,7 @@ id = 0; awb_status.status.cur_r_gain, awb_status.status.cur_b_gain, awb_status.status.cur_ct + //(INT)(IRSHTTER) ); //DBG_DUMP("isp Buf=%s\r\n",Buf); diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.h b/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.h index 408f2aee9..ea5ba1ef4 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.h +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/MovieStamp/MovieStamp.h @@ -6,7 +6,7 @@ #include "GxVideoFile.h" #include "hdal.h" -#define MOVIE_ISP_LOG DISABLE +#define MOVIE_ISP_LOG ENABLE #if (MOVIE_ISP_LOG == ENABLE) #undef WATERLOGO_FUNCTION diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.c b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.c index b81e3b5e5..914ba8b8b 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.c +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.c @@ -65,7 +65,7 @@ #define STKSIZE_PHOTOFAST_CMDTSK 4096 #define FASTCAPTURE_AE_DEBUG 1 - +#define VD_TICK_BUF_SIZE (PHOTOFAST_CAP_FRAME_CNT * 3) //global variable static _FDB_SN_FASTBOOT g_fdb_sn_fastboot={ FALSE, @@ -98,6 +98,8 @@ static BOOL g_bPreViewPullFlag = TRUE; static UINT32 g_bFrmCnt = 0; static UINT32 g_exif_buf_pa = 0, g_exif_buf_va = 0; static UINT32 g_u32PrvCapCnt = 0; +static VOS_TICK g_tickBuf[VD_TICK_BUF_SIZE] = {0}; +static UINT32 g_vcap_trigger_frm_count = 0XFFFFFFFF; /* start from 0 */ //extern extern const unsigned char gDemoKit_Font[]; @@ -112,6 +114,7 @@ INT32 PhotoFast_WriteFile(UINT32 Addr, UINT32 Size, UINT32 Fmt, UINT32 uiPathId) static void PhotoFast_ShutDown(void); void Set_NIGHTMODE(UINT32 id, UINT8 isSnapVideo); void Set_AEMODE(UINT32 id); +void PhotoFast_TriggerFrm_Dump(void); static HD_RESULT init_enc_module(void) { @@ -1295,14 +1298,22 @@ THREAD_RETTYPE PhotoFast_InitFileNamingThread(void *arg) extern void DrvGOIO_Turn_Onoff_IRCUT(UINT8 onoff); extern void isp_dbg_set_dbg_mode(ISP_ID id, UINT32 cmd); extern void setet_preset_param(void); +static UINT32 capturcnt = 0; +static BOOL captureflag = FALSE; +UINT32 Cap_cnt=0; THREAD_RETTYPE PhotoFast_FlowPreviewThread(void *arg) { HD_RESULT hd_ret; + HD_VIDEO_FRAME video_cap_frame = {0}; HD_VIDEO_FRAME video_frame = {0}; - HD_PATH_ID vprc_path=0, vout_path=0; + HD_PATH_ID vprc_path = 0, vout_path = 0, vcap_path = 0; UINT32 max_cnt = 0; BOOL start_cap = FALSE; + //IQT_SHARPNESS_LV sharpness_lv = {0}; + //IQT_NR_LV nr_lv = {0}; + AET_STATUS_INFO ae_status = {0}; + flow_preview_get_path(&vcap_path, FLOW_PREIVEW_VCAP_PATH, 0); flow_preview_get_path(&vprc_path, FLOW_PREIVEW_VPRC_PATH, 0); flow_preview_get_path(&vout_path, FLOW_PREIVEW_VOUT_PATH, 0); @@ -1348,15 +1359,41 @@ THREAD_RETTYPE PhotoFast_FlowPreviewThread(void *arg) // nvt_cmdsys_runcmd("vprc info"); // nvt_cmdsys_runcmd("ctl_ipp dump_hdl_all"); nvt_cmdsys_runcmd("ae dbg 0 256 1 "); - isp_dbg_set_dbg_mode(0, 0x0003000 ); + // isp_dbg_set_dbg_mode(0, 0x0003000 ); nvt_cmdsys_runcmd("ae set_speed 0 128 600 600 100 "); + //nvt_cmdsys_runcmd("iq dbg 0 0 "); + //nvt_cmdsys_runcmd("iq dbg 0 8 "); +/* + nr_lv.id = 0; + nr_lv.lv = 200; + vendor_isp_set_iq(IQT_ITEM_NR_LV, &nr_lv); //50~200 + sharpness_lv.id = 0; + sharpness_lv.lv = 50; + vendor_isp_set_iq(IQT_ITEM_SHARPNESS_LV, &sharpness_lv); +*/ + } #endif while(g_bPreViewPullFlag) { - if (g_bFrmCnt == 7){; + /*if (g_bFrmCnt == 6){; + Set_AEMODE(1); + setet_preset_param(); + }*/ + if ((g_bFrmCnt > 2)&&(captureflag == FALSE)){ + vendor_isp_get_ae(AET_ITEM_STATUS, &ae_status); + if ((ae_status.status_info.state_adj ==0)|| (++g_bFrmCnt==10)){ + Cap_cnt=g_bFrmCnt; + captureflag = TRUE; + capturcnt = 0; Set_AEMODE(1); setet_preset_param(); } + } + else + { + ++g_bFrmCnt; + } +//DBG_ERR(">>>>>>> adj %d lum %d explum %d exp %d iso %d\r\n",ae_status.status_info.state_adj,ae_status.status_info.lum,ae_status.status_info.expect_lum,ae_status.status_info.iso_gain[0],ae_status.status_info.expotime[0]); #if POWERON_FAST_SLICE_ENC_VER2 == ENABLE @@ -1372,6 +1409,28 @@ THREAD_RETTYPE PhotoFast_FlowPreviewThread(void *arg) } #endif + + +#if HUNTING_PHOTO_FAST_AE_60_FPS == ENABLE + if((hd_ret = hd_videocap_pull_out_buf(vcap_path, &video_cap_frame, -1)) != HD_OK){ + DBG_ERR("failed to hd_videocap_pull_out_buf, er=%d\n", (int)hd_ret); + goto exit; + } + + if((hd_ret = hd_videoproc_push_in_buf(vprc_path, &video_cap_frame, NULL, -1)) != HD_OK){ + DBG_ERR("failed to hd_videoproc_push_in_buf, er=%d\n", (int)hd_ret); + goto exit; + } + + if((hd_ret = hd_videocap_release_out_buf(vcap_path, &video_cap_frame)) != HD_OK){ + DBG_ERR("failed to hd_videocap_release_out_buf, er=%d\n", (int)hd_ret); + goto exit; + } +#else + (void) vcap_path; + (void) video_cap_frame; +#endif + if ((hd_ret = hd_videoproc_pull_out_buf(vprc_path, &video_frame, -1)) != HD_OK) { DBG_ERR("failed to hd_videoproc_pull_out_buf, er=%d\n", (int)hd_ret); goto exit; @@ -1380,8 +1439,25 @@ THREAD_RETTYPE PhotoFast_FlowPreviewThread(void *arg) //if(g_bFrmCnt < PHOTOFAST_CAP_FRAME_CNT){ // vos_perf_list_mark("yuv", __LINE__, 0); //} + /* if(0){//++g_bFrmCnt >= 5){//PHOTOFAST_CAP_FRAME_CNT){ - if(++g_bFrmCnt >= 12){//PHOTOFAST_CAP_FRAME_CNT){ + nr_lv.id = 0; + nr_lv.lv = 100; + vendor_isp_set_iq(IQT_ITEM_NR_LV, &nr_lv); //50~200 + sharpness_lv.id = 0; + sharpness_lv.lv = 100; + vendor_isp_set_iq(IQT_ITEM_SHARPNESS_LV, &sharpness_lv); + + }*/ + if (captureflag) capturcnt++; + if (capturcnt>6) { + // DBG_ERR(">>>>>>>>>>>>capture adj:%d capcnt:%d frmcnt:%d\r\n",ae_status.status_info.state_adj,capturcnt,g_bFrmCnt); + //if(++g_bFrmCnt >= 10){//PHOTOFAST_CAP_FRAME_CNT){ +#if HUNTING_PHOTO_FAST_AE_60_FPS == ENABLE + PhotoFast_SetTriggerFrmCnt(video_cap_frame.count - 1); /* unbind mode , use vcap frame count */ +#else + PhotoFast_SetTriggerFrmCnt(video_frame.count - 1); /* bind mode , vprc frame count = vcap frame count */ +#endif start_cap = TRUE; //Set_AEMODE(1); } @@ -1549,6 +1625,7 @@ static void PhotoFast_ShutDown(void) #if POWERON_BOOT_REPORT == ENABLE vos_perf_list_dump(); + PhotoFast_TriggerFrm_Dump(); #endif #if HUNTING_CAMERA_MCU sf_mcu_reg_set(SF_MCU_POWEROFF,0); @@ -1560,6 +1637,7 @@ static void PhotoFast_ShutDown(void) vos_perf_list_mark("pwr off", __LINE__, 0); #if POWERON_BOOT_REPORT == ENABLE vos_perf_list_dump(); + PhotoFast_TriggerFrm_Dump(); #endif #if HUNTING_CAMERA_MCU @@ -1649,10 +1727,13 @@ void Set_AEMODE(UINT32 id) ae_manual.id = 0; vendor_isp_get_ae(AET_ITEM_MANUAL, &ae_manual); //DBG_ERR(">> aet manual exp %d iso %d\r\n",ae_manual.manual.expotime,ae_manual.manual.iso_gain); -if (id == 1) +if (id == 1){ ae_manual.manual.mode = 2; -else + nvt_cmdsys_runcmd("ae dbg 0 0 0 "); +} +else { ae_manual.manual.mode = 0; +} DBG_ERR(">> >>>>>>>>>aet manual mode %d\r\n",ae_manual.manual.mode); vendor_isp_set_ae(AET_ITEM_MANUAL, &ae_manual); @@ -1675,5 +1756,65 @@ else } } +void PhotoFast_TriggerFrm_Dump(void) +{ + if(g_vcap_trigger_frm_count < VD_TICK_BUF_SIZE){ + + DBG_DUMP("\n\n**********************************************************\n" + " Trigger Speed(vcap frame count = %lu) : %lu us\n" + "**********************************************************\n", + g_vcap_trigger_frm_count + 1, g_tickBuf[g_vcap_trigger_frm_count]); + } + else if(g_vcap_trigger_frm_count == 0xFFFFFFFF){ + DBG_DUMP("\n\n**********************************************************\n" + " Trigger Speed : Unknown\n" + "**********************************************************\n"); + } + else{ + DBG_DUMP("\n\n**********************************************************\n" + " Trigger Speed : Err\n" + "**********************************************************\n"); + } +} + +BOOL PhotoFast_SetTriggerFrmCnt(UINT32 cnt) +{ + g_vcap_trigger_frm_count = cnt; + return TRUE; +} + +BOOL PhotoFast_SetTick(UINT32 cnt, VOS_TICK tick) +{ + if(cnt > VD_TICK_BUF_SIZE){ + DBG_WRN("%lu exceed tick buffer(%lu)\n", cnt, VD_TICK_BUF_SIZE); + return FALSE; + } + + g_tickBuf[cnt] = tick; + return TRUE; +} + +BOOL PhotoFast_GetTick(UINT32 cnt, VOS_TICK* tick) +{ + if(tick == NULL){ + DBG_WRN("tick is null!\n"); + return FALSE; + } + + if(cnt > VD_TICK_BUF_SIZE){ + DBG_WRN("%lu exceed tick buffer(%lu)!\n", cnt, VD_TICK_BUF_SIZE); + return FALSE; + } + + *tick = g_tickBuf[cnt]; + + return TRUE; +} + +UINT32 PhotoFast_GetTickBufSize(void) +{ + return VD_TICK_BUF_SIZE; +} + #endif diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.h b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.h index 78c8cb2e8..45e910dd7 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.h +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFast.h @@ -54,4 +54,10 @@ extern THREAD_RETTYPE PhotoFast_EncodeBsPullThread(void *arg); extern THREAD_RETTYPE PhotoFast_FlowPreviewThread(void *arg); extern void PhotoFast_PhotoClose(void); +extern BOOL PhotoFast_SetTick(UINT32 cnt, VOS_TICK tick); /* start from 0 */ +extern BOOL PhotoFast_GetTick(UINT32 cnt, VOS_TICK* tick); /* start from 0 */ +extern BOOL PhotoFast_SetTriggerFrmCnt(UINT32 cnt); /* trigger vcap frame count , get from HD_VIDEO_FRAME */ +extern UINT32 PhotoFast_GetTickBufSize(void); + + #endif //_UIAPP_PHOTO_H_ diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastCapDateImprint.c b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastCapDateImprint.c index af2634811..d9e58e0fe 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastCapDateImprint.c +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastCapDateImprint.c @@ -47,6 +47,10 @@ typedef struct { char photo_aesteam[64]={0}; extern UINT16 IRSHTTER; +extern UINT32 Cap_cnt; +extern UINT32 ae_preset_exp; +extern UINT32 ae_preset_iso; + void PhotoStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) { AET_STATUS_INFO ae_status = {0}; @@ -100,11 +104,20 @@ void PhotoStamp_get_isp_status(UINT32 id, char* Buf, UINT32 BufLen) '\0' );*/ //DBG_DUMP("isp Buf=%s\r\n",Buf); - snprintf(Buf, BufLen, "%d %d %3d %d %04d/%02d/%02d %02d:%02d:%02d", + snprintf(Buf, BufLen, "%d %d %3d %d %d %3d %3d %3d %4d %d %d %d %d %04d/%02d/%02d %02d:%02d:%02d", + (INT)(ae_status.status_info.state_adj), + (INT)(ae_status.status_info.lum), + (INT)(ae_status.status_info.expect_lum), (INT)(ae_status.status_info.iso_gain[0]), (INT)(ae_status.status_info.expotime[0]), (INT)(ae_status.status_info.lv/100000), + (INT)(awb_status.status.cur_r_gain), + (INT)(awb_status.status.cur_b_gain), + (INT)(awb_status.status.cur_ct), IRSHTTER, + Cap_cnt, + ae_preset_exp, + ae_preset_iso, Curr_gsDateTime.tm_year, Curr_gsDateTime.tm_mon, Curr_gsDateTime.tm_mday, diff --git a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastSliceEncode.c b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastSliceEncode.c index f24fee691..391ca7514 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastSliceEncode.c +++ b/rtos/code/application/source/cardv/SrcCode/UIApp/PhotoFast/PhotoFastSliceEncode.c @@ -1758,6 +1758,7 @@ INT32 PhotoFast_SliceEncode_CB2(void* user_data) ExifVendor_Write0thIFD(EXIF_HDL_ID_1); ExifVendor_WriteExifIFD(EXIF_HDL_ID_1); ExifVendor_Write0thIntIFD(EXIF_HDL_ID_1); + ExifVendor_WriteGPSIFD(EXIF_HDL_ID_1); if (EXIF_CreateExif(EXIF_HDL_ID_1, &exif_data, &thumb_jpg) != EXIF_ER_OK) { DBG_ERR("Create Exif fail\r\n"); diff --git a/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h b/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h index 7b540231b..4a4a85832 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h +++ b/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UICfgDefault.h @@ -166,7 +166,7 @@ #endif #define DEFAULT_ETHCAM_TX_IP_ADDR 0 //0xc00a8c0 -#define DEFAULT_BOOT_WORK_MODE SF_CAM_MODE_PHOTO_VIDEO//SF_CAM_MODE_PHOTO +#define DEFAULT_BOOT_WORK_MODE SF_CAM_MODE_PHOTO_VIDEO// #define DEFAULT_SF_CAMID SF_CAMID_OFF #define DEFAULT_FLASH_LED SF_FLASH_LED_HIGH #define DEFAULT_NIGHT_MODE SF_NIGHT_MODE_MIN_BLUR//SF_NIGHT_MODE_BALANCED diff --git a/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c b/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c index 314719e88..32bbf62ef 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c +++ b/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.c @@ -934,6 +934,7 @@ void SysSetFixedFlagSysInit(void) void SysResetFlag(void) { + UIMenuStoreInfo *puiPara = sf_ui_para_get(); // Set system flag default value here // Photo SysSetFlag(FL_PHOTO_SIZE, DEFAULT_PHOTO_SIZE); @@ -1079,8 +1080,31 @@ void SysResetFlag(void) SysSetFlag(PirSensitivity, DEFAULT_PIR_SENSITIVITY); SysSetFlag(PirDelaySwitch, DEFAULT_PIR_DELAY_SWITCH); SysSetFlag(TimelapseSwitch, DEFAULT_TIMELAPSE_SWITCH); + if(SysGetFlag(TimelapseSwitch)) + { + puiPara->TimelapseTime.Hour = 0; + puiPara->TimelapseTime.Min = 0; + puiPara->TimelapseTime.Sec = 5; + } + SysSetFlag(WorkTime1Switch, DEFAULT_WORKTIME_SWITCH); + if(SysGetFlag(WorkTime1Switch)) + { + puiPara->WorkTime[0].StartTime.Hour = 16; + puiPara->WorkTime[0].StartTime.Min = 0; + puiPara->WorkTime[0].StopTime.Hour = 20; + puiPara->WorkTime[0].StopTime.Min = 0; + } + SysSetFlag(WorkTime2Switch, DEFAULT_WORKTIME_SWITCH); + if(SysGetFlag(WorkTime2Switch)) + { + puiPara->WorkTime[1].StartTime.Hour = 5; + puiPara->WorkTime[1].StartTime.Min = 0; + puiPara->WorkTime[1].StopTime.Hour = 8; + puiPara->WorkTime[1].StopTime.Min = 0; + } + SysSetFlag(SimAutoSwitch, DEFAULT_SIM_AUTO_SWITCH); SysSetFlag(SendMaxNum, DEFAULT_SEND_MAX_NUM); SysSetFlag(GprsMode, DEFAULT_GPRS_MODE); diff --git a/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h b/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h index f9b367884..e7b828103 100755 --- a/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h +++ b/rtos/code/application/source/cardv/SrcCode/UIWnd/LVGL_SPORTCAM/UIInfo/UIInfo.h @@ -6,10 +6,16 @@ #include #endif -//============Sifar==============///Payton +#ifndef SF_DATA_UI_TYPE +#define SF_DATA_UI_TYPE + #define SF_TIMER_MAX_NUMBER 2 typedef struct sf_PARA_TIME_S -{ +{ + UINT16 Year; + UINT16 Mon; + UINT16 Day; + UINT8 Hour; UINT8 Min; UINT8 Sec; @@ -20,6 +26,7 @@ typedef struct sf_WORKTIME_S SF_PARA_TIME_S StartTime; SF_PARA_TIME_S StopTime; } SF_WORKTIME_S; +#endif //============Sifar==============///Payton /** diff --git a/rtos/code/driver/na51089/source/mcu/sf_mcu_dev.c b/rtos/code/driver/na51089/source/mcu/sf_mcu_dev.c index 254f4906d..cda8334e5 100755 --- a/rtos/code/driver/na51089/source/mcu/sf_mcu_dev.c +++ b/rtos/code/driver/na51089/source/mcu/sf_mcu_dev.c @@ -1582,6 +1582,37 @@ UINT8 sf_mcu_reg_set(MCUParam_t attrId, UINT8 val) mcuReg[i] = WORKTIME1_STOP_MINUTE; mcuData[i++] = 0; } + + if(SysGetFlag(WorkTime2Switch)) + { + mcuReg[i] = WORKTIME2_SWITCH; + mcuData[i++] = 0xFF; + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = puiPara->WorkTime[1].StartTime.Hour; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = puiPara->WorkTime[1].StartTime.Min; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = puiPara->WorkTime[1].StopTime.Hour; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = puiPara->WorkTime[1].StopTime.Min; + } + else + { + mcuReg[i] = WORKTIME2_SWITCH; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_START_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_START_MINUTE; + mcuData[i++] = 0; + + mcuReg[i] = WORKTIME2_STOP_HOUR; + mcuData[i++] = 0; + mcuReg[i] = WORKTIME2_STOP_MINUTE; + mcuData[i++] = 0; + } if((SysGetFlag(GpsSwitch) || SysGetFlag(FristSendDailyAndGps)) && (sf_get_mode_flag() || paraSyncFlag)) { diff --git a/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_ae_0.dtsi b/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_ae_0.dtsi index b5dcfdb42..ddbf2d15e 100755 --- a/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_ae_0.dtsi +++ b/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_ae_0.dtsi @@ -7,7 +7,7 @@ version-info = [00 01 00 01]; ae_expect_lum { size = [b0 00 00 00]; - data = [2f 00 00 00 32 00 00 00 3a 00 00 00 3a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 43 00 00 00 46 00 00 00 50 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 46 00 00 00 50 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00]; + data = [3c 00 00 00 3c 00 00 00 3d 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3d 00 00 00 41 00 00 00 46 00 00 00 4d 00 00 00 54 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 46 00 00 00 50 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00]; }; ae_la_clamp { size = [50 01 00 00]; @@ -23,7 +23,7 @@ }; ae_curve_gen_movie { size = [10 01 00 00]; - data = [f4 01 00 00 01 00 00 00 2c 00 00 00 64 00 00 00 00 00 00 00 00 00 00 00 1a 41 00 00 90 01 00 00 00 00 00 00 00 00 00 00 35 82 00 00 90 01 00 00 00 00 00 00 00 00 00 00 35 82 00 00 40 06 00 00 00 00 00 00 00 00 00 00 35 82 00 00 00 32 00 00 00 00 00 00 00 00 00 00 80 38 01 00 00 19 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 19 00 00 01 00 00 00 10 00 00 00 00 00 00 00 b8 0b 00 00 b8 0b 00 00 60 09 00 00 e2 04 00 00 d0 07 00 00 d0 07 00 00 dc 05 00 00 dc 05 00 00 b0 04 00 00 b0 04 00 00 00 00 00 00 f6 ec 00 00 00 00 00 00]; + data = [f4 01 00 00 00 00 00 00 2c 00 00 00 64 00 00 00 00 00 00 00 00 00 00 00 1a 41 00 00 90 01 00 00 00 00 00 00 00 00 00 00 35 82 00 00 90 01 00 00 00 00 00 00 00 00 00 00 35 82 00 00 40 06 00 00 00 00 00 00 00 00 00 00 35 82 00 00 00 32 00 00 00 00 00 00 00 00 00 00 80 38 01 00 00 19 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 19 00 00 01 00 00 00 10 00 00 00 01 00 00 00 b8 0b 00 00 b8 0b 00 00 60 09 00 00 e2 04 00 00 d0 07 00 00 d0 07 00 00 dc 05 00 00 dc 05 00 00 b0 04 00 00 b0 04 00 00 00 00 00 00 f6 ec 00 00 00 00 00 00]; }; ae_meter_window { size = [00 01 00 00]; diff --git a/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0.dtsi b/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0.dtsi index 7567801db..7e8741b89 100755 --- a/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0.dtsi +++ b/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0.dtsi @@ -11,7 +11,7 @@ }; iq_nr { size = [f4 12 00 00]; - data = [01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 00 00 00 00 0c 00 00 00 80 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 0c 00 00 00 0c 00 00 00 0d 00 00 00 0d 00 00 00 0e 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 02 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 08 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 0b 00 00 00 0c 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0c 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 08 00 00 00 09 00 00 00 0a 00 00 00 0b 00 00 00 0c 00 00 00 0d 00 00 00 0e 00 00 00 0f 00 00 00 10 00 00 00 11 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 05 00 00 00 07 00 00 00 09 00 00 00 0a 00 00 00 0e 00 00 00 01 00 00 00 07 00 00 00 0c 00 00 00 11 00 00 00 13 00 00 00 13 00 00 00 0d 00 00 00 0f 00 00 00 10 00 00 00 12 00 00 00 13 00 00 00 14 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 1a 00 00 00 00 00 00 00 0f 00 00 00 16 00 00 00 1b 00 00 00 1f 00 00 00 2c 00 00 00 00 00 00 00 0a 00 00 00 0c 00 00 00 0e 00 00 00 10 00 00 00 12 00 00 00 14 00 00 00 16 00 00 00 17 00 00 00 19 00 00 00 1a 00 00 00 1b 00 00 00 1d 00 00 00 1e 00 00 00 1f 00 00 00 20 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 18 00 00 00 10 00 00 00 18 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 02 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 0d 00 00 00 1b 00 00 00 21 00 00 00 25 00 00 00 29 00 00 00 2d 00 00 00 30 00 00 00 33 00 00 00 35 00 00 00 38 00 00 00 3a 00 00 00 3c 00 00 00 3e 00 00 00 40 00 00 00 42 00 00 00 44 00 00 00 46 00 00 00 00 00 00 00 1e 00 00 00 2a 00 00 00 34 00 00 00 3c 00 00 00 55 00 00 00 00 00 00 00 12 00 00 00 19 00 00 00 1f 00 00 00 24 00 00 00 28 00 00 00 2c 00 00 00 2f 00 00 00 32 00 00 00 36 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 40 00 00 00 43 00 00 00 45 00 00 00 48 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 1d 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 00 00 00 00 0e 00 00 00 14 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 23 00 00 00 26 00 00 00 28 00 00 00 2b 00 00 00 2d 00 00 00 2f 00 00 00 31 00 00 00 33 00 00 00 35 00 00 00 37 00 00 00 39 00 00 00 00 00 00 00 26 00 00 00 36 00 00 00 42 00 00 00 4d 00 00 00 6c 00 00 00 01 00 00 00 47 00 00 00 35 00 00 00 3e 00 00 00 31 00 00 00 37 00 00 00 3c 00 00 00 41 00 00 00 46 00 00 00 4a 00 00 00 4e 00 00 00 51 00 00 00 55 00 00 00 58 00 00 00 5c 00 00 00 5f 00 00 00 62 00 00 00 0f 00 00 00 00 00 00 00 20 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 30 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 55 00 00 00 79 00 00 00 94 00 00 00 ab 00 00 00 f2 00 00 00 00 00 00 00 21 00 00 00 2f 00 00 00 3a 00 00 00 43 00 00 00 4b 00 00 00 52 00 00 00 58 00 00 00 5f 00 00 00 64 00 00 00 6a 00 00 00 6f 00 00 00 74 00 00 00 79 00 00 00 7d 00 00 00 82 00 00 00 86 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 12 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 79 00 00 00 ab 00 00 00 d2 00 00 00 f2 00 00 00 57 01 00 00 00 00 00 00 3a 00 00 00 52 00 00 00 65 00 00 00 74 00 00 00 82 00 00 00 8f 00 00 00 9a 00 00 00 a5 00 00 00 af 00 00 00 b8 00 00 00 c1 00 00 00 ca 00 00 00 d2 00 00 00 da 00 00 00 e2 00 00 00 e9 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 70 00 00 00 9f 00 00 00 c3 00 00 00 e1 00 00 00 3f 01 00 00 00 00 00 00 54 00 00 00 76 00 00 00 91 00 00 00 a8 00 00 00 bb 00 00 00 cd 00 00 00 de 00 00 00 ed 00 00 00 fb 00 00 00 09 01 00 00 16 01 00 00 22 01 00 00 2e 01 00 00 3a 01 00 00 45 01 00 00 50 01 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 09 00 80 00 00 00 00 00 10 00 00 00 16 00 00 00 1c 00 00 00 20 00 00 00 2d 00 00 00 00 00 00 00 12 00 00 00 18 00 00 00 20 00 00 00 25 00 00 00 2a 00 00 00 2e 00 00 00 31 00 00 00 35 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 41 00 00 00 43 00 00 00 46 00 00 00 48 00 00 00 4b 00 00 00 00 00 00 00 1a 01 00 00 8f 01 00 00 e9 01 00 00 34 02 00 00 1e 03 00 00 00 00 00 00 40 00 00 00 5a 00 00 00 6e 00 00 00 80 00 00 00 8f 00 00 00 9c 00 00 00 a9 00 00 00 b5 00 00 00 c0 00 00 00 ca 00 00 00 d4 00 00 00 dd 00 00 00 e6 00 00 00 ef 00 00 00 f7 00 00 00 00 01 00 00 00 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 18 00 00 00 02 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00]; + data = [01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 00 00 00 00 0c 00 00 00 80 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 08 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0c 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 08 00 00 00 09 00 00 00 0a 00 00 00 0b 00 00 00 0c 00 00 00 0d 00 00 00 0e 00 00 00 0f 00 00 00 10 00 00 00 11 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 05 00 00 00 07 00 00 00 09 00 00 00 0a 00 00 00 0e 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 10 00 00 00 12 00 00 00 12 00 00 00 0c 00 00 00 0e 00 00 00 0f 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 15 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 00 00 00 00 0f 00 00 00 16 00 00 00 1b 00 00 00 1f 00 00 00 2c 00 00 00 00 00 00 00 0a 00 00 00 0c 00 00 00 0e 00 00 00 10 00 00 00 12 00 00 00 14 00 00 00 16 00 00 00 17 00 00 00 19 00 00 00 1a 00 00 00 1b 00 00 00 1d 00 00 00 1e 00 00 00 1f 00 00 00 20 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 18 00 00 00 10 00 00 00 18 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 02 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 00 00 00 00 1a 00 00 00 20 00 00 00 24 00 00 00 28 00 00 00 2c 00 00 00 2f 00 00 00 32 00 00 00 34 00 00 00 37 00 00 00 39 00 00 00 3b 00 00 00 3d 00 00 00 3f 00 00 00 41 00 00 00 43 00 00 00 45 00 00 00 00 00 00 00 1e 00 00 00 2a 00 00 00 34 00 00 00 3c 00 00 00 55 00 00 00 00 00 00 00 12 00 00 00 19 00 00 00 1f 00 00 00 24 00 00 00 28 00 00 00 2c 00 00 00 2f 00 00 00 32 00 00 00 36 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 40 00 00 00 43 00 00 00 45 00 00 00 48 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 1d 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 00 00 00 00 0e 00 00 00 14 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 23 00 00 00 26 00 00 00 28 00 00 00 2b 00 00 00 2d 00 00 00 2f 00 00 00 31 00 00 00 33 00 00 00 35 00 00 00 37 00 00 00 39 00 00 00 00 00 00 00 26 00 00 00 36 00 00 00 42 00 00 00 4d 00 00 00 6c 00 00 00 01 00 00 00 47 00 00 00 35 00 00 00 3e 00 00 00 31 00 00 00 37 00 00 00 3c 00 00 00 41 00 00 00 46 00 00 00 4a 00 00 00 4e 00 00 00 51 00 00 00 55 00 00 00 58 00 00 00 5c 00 00 00 5f 00 00 00 62 00 00 00 0f 00 00 00 00 00 00 00 20 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 30 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 55 00 00 00 79 00 00 00 94 00 00 00 ab 00 00 00 f2 00 00 00 00 00 00 00 21 00 00 00 2f 00 00 00 3a 00 00 00 43 00 00 00 4b 00 00 00 52 00 00 00 58 00 00 00 5f 00 00 00 64 00 00 00 6a 00 00 00 6f 00 00 00 74 00 00 00 79 00 00 00 7d 00 00 00 82 00 00 00 86 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 12 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 79 00 00 00 ab 00 00 00 d2 00 00 00 f2 00 00 00 57 01 00 00 00 00 00 00 3a 00 00 00 52 00 00 00 65 00 00 00 74 00 00 00 82 00 00 00 8f 00 00 00 9a 00 00 00 a5 00 00 00 af 00 00 00 b8 00 00 00 c1 00 00 00 ca 00 00 00 d2 00 00 00 da 00 00 00 e2 00 00 00 e9 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 70 00 00 00 9f 00 00 00 c3 00 00 00 e1 00 00 00 3f 01 00 00 00 00 00 00 54 00 00 00 76 00 00 00 91 00 00 00 a8 00 00 00 bb 00 00 00 cd 00 00 00 de 00 00 00 ed 00 00 00 fb 00 00 00 09 01 00 00 16 01 00 00 22 01 00 00 2e 01 00 00 3a 01 00 00 45 01 00 00 50 01 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 09 00 80 00 00 00 00 00 10 00 00 00 16 00 00 00 1c 00 00 00 20 00 00 00 2d 00 00 00 00 00 00 00 12 00 00 00 18 00 00 00 20 00 00 00 25 00 00 00 2a 00 00 00 2e 00 00 00 31 00 00 00 35 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 41 00 00 00 43 00 00 00 46 00 00 00 48 00 00 00 4b 00 00 00 00 00 00 00 1a 01 00 00 8f 01 00 00 e9 01 00 00 34 02 00 00 1e 03 00 00 00 00 00 00 40 00 00 00 5a 00 00 00 6e 00 00 00 80 00 00 00 8f 00 00 00 9c 00 00 00 a9 00 00 00 b5 00 00 00 c0 00 00 00 ca 00 00 00 d4 00 00 00 dd 00 00 00 e6 00 00 00 ef 00 00 00 f7 00 00 00 00 01 00 00 00 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 18 00 00 00 02 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00]; }; iq_cfa { size = [54 05 00 00]; @@ -23,7 +23,7 @@ }; iq_gamma { size = [94 0e 00 00]; - data = [00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 19 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 32 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 4b 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 64 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 25 00 00 00 49 00 00 00 6b 00 00 00 8b 00 00 00 a9 00 00 00 c6 00 00 00 e1 00 00 00 f1 00 00 00 01 01 00 00 11 01 00 00 21 01 00 00 30 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 68 01 00 00 75 01 00 00 82 01 00 00 8f 01 00 00 9b 01 00 00 a6 01 00 00 b1 01 00 00 bc 01 00 00 c7 01 00 00 d1 01 00 00 db 01 00 00 e4 01 00 00 ed 01 00 00 f6 01 00 00 fe 01 00 00 06 02 00 00 0d 02 00 00 14 02 00 00 1b 02 00 00 22 02 00 00 29 02 00 00 30 02 00 00 36 02 00 00 3d 02 00 00 44 02 00 00 4b 02 00 00 52 02 00 00 59 02 00 00 5f 02 00 00 66 02 00 00 6d 02 00 00 73 02 00 00 7a 02 00 00 80 02 00 00 87 02 00 00 8d 02 00 00 93 02 00 00 9a 02 00 00 a0 02 00 00 a6 02 00 00 ac 02 00 00 b3 02 00 00 b9 02 00 00 bf 02 00 00 c5 02 00 00 cb 02 00 00 d1 02 00 00 d7 02 00 00 dd 02 00 00 e3 02 00 00 e8 02 00 00 ee 02 00 00 f4 02 00 00 fa 02 00 00 ff 02 00 00 04 03 00 00 09 03 00 00 0e 03 00 00 13 03 00 00 18 03 00 00 1d 03 00 00 21 03 00 00 26 03 00 00 2b 03 00 00 30 03 00 00 35 03 00 00 3a 03 00 00 3e 03 00 00 43 03 00 00 48 03 00 00 4d 03 00 00 51 03 00 00 56 03 00 00 5b 03 00 00 5f 03 00 00 64 03 00 00 68 03 00 00 6d 03 00 00 72 03 00 00 76 03 00 00 7b 03 00 00 7f 03 00 00 84 03 00 00 88 03 00 00 8c 03 00 00 91 03 00 00 95 03 00 00 99 03 00 00 9e 03 00 00 a2 03 00 00 a6 03 00 00 ab 03 00 00 af 03 00 00 b3 03 00 00 b7 03 00 00 bb 03 00 00 bf 03 00 00 c4 03 00 00 c8 03 00 00 cc 03 00 00 d0 03 00 00 d4 03 00 00 d8 03 00 00 dc 03 00 00 e0 03 00 00 e4 03 00 00 e8 03 00 00 eb 03 00 00 ef 03 00 00 f3 03 00 00 f7 03 00 00 fb 03 00 00 ff 03 00 00 07 00 00 00 00 00 00 00 3d 00 00 00 71 00 00 00 98 00 00 00 ba 00 00 00 d3 00 00 00 ec 00 00 00 03 01 00 00 19 01 00 00 2c 01 00 00 3f 01 00 00 4f 01 00 00 5e 01 00 00 69 01 00 00 76 01 00 00 84 01 00 00 91 01 00 00 9e 01 00 00 ab 01 00 00 b7 01 00 00 c3 01 00 00 ce 01 00 00 d9 01 00 00 e3 01 00 00 ed 01 00 00 f3 01 00 00 fa 01 00 00 01 02 00 00 08 02 00 00 0f 02 00 00 16 02 00 00 1d 02 00 00 23 02 00 00 2a 02 00 00 31 02 00 00 37 02 00 00 3e 02 00 00 44 02 00 00 4b 02 00 00 51 02 00 00 57 02 00 00 5e 02 00 00 64 02 00 00 6a 02 00 00 70 02 00 00 76 02 00 00 7c 02 00 00 83 02 00 00 89 02 00 00 8f 02 00 00 94 02 00 00 9a 02 00 00 a0 02 00 00 a5 02 00 00 ab 02 00 00 b0 02 00 00 b6 02 00 00 bb 02 00 00 c0 02 00 00 c5 02 00 00 cb 02 00 00 d0 02 00 00 d5 02 00 00 da 02 00 00 df 02 00 00 e4 02 00 00 e9 02 00 00 ee 02 00 00 f3 02 00 00 f9 02 00 00 fe 02 00 00 03 03 00 00 08 03 00 00 0e 03 00 00 13 03 00 00 18 03 00 00 1d 03 00 00 22 03 00 00 27 03 00 00 2c 03 00 00 31 03 00 00 36 03 00 00 3b 03 00 00 40 03 00 00 44 03 00 00 49 03 00 00 4e 03 00 00 53 03 00 00 58 03 00 00 5c 03 00 00 61 03 00 00 66 03 00 00 6a 03 00 00 6f 03 00 00 74 03 00 00 78 03 00 00 7d 03 00 00 81 03 00 00 86 03 00 00 8a 03 00 00 8e 03 00 00 93 03 00 00 97 03 00 00 9b 03 00 00 a0 03 00 00 a4 03 00 00 a8 03 00 00 ac 03 00 00 b1 03 00 00 b5 03 00 00 b9 03 00 00 bd 03 00 00 c1 03 00 00 c5 03 00 00 c9 03 00 00 cd 03 00 00 d1 03 00 00 d5 03 00 00 d9 03 00 00 dd 03 00 00 e1 03 00 00 e5 03 00 00 e8 03 00 00 ec 03 00 00 f0 03 00 00 f4 03 00 00 f7 03 00 00 fb 03 00 00 ff 03 00 00 05 00 00 00 00 00 00 00 2b 00 00 00 50 00 00 00 6a 00 00 00 86 00 00 00 a2 00 00 00 bd 00 00 00 d5 00 00 00 ec 00 00 00 00 01 00 00 11 01 00 00 21 01 00 00 2e 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 6a 01 00 00 78 01 00 00 86 01 00 00 93 01 00 00 a0 01 00 00 ad 01 00 00 ba 01 00 00 c6 01 00 00 d3 01 00 00 df 01 00 00 ea 01 00 00 f6 01 00 00 01 02 00 00 0c 02 00 00 17 02 00 00 22 02 00 00 2c 02 00 00 36 02 00 00 40 02 00 00 4a 02 00 00 54 02 00 00 5d 02 00 00 66 02 00 00 70 02 00 00 78 02 00 00 81 02 00 00 8a 02 00 00 92 02 00 00 9a 02 00 00 a2 02 00 00 aa 02 00 00 b2 02 00 00 ba 02 00 00 c1 02 00 00 c9 02 00 00 d0 02 00 00 d7 02 00 00 de 02 00 00 e5 02 00 00 eb 02 00 00 f2 02 00 00 f8 02 00 00 fe 02 00 00 04 03 00 00 0b 03 00 00 10 03 00 00 16 03 00 00 1c 03 00 00 22 03 00 00 27 03 00 00 2c 03 00 00 32 03 00 00 37 03 00 00 3c 03 00 00 41 03 00 00 46 03 00 00 4b 03 00 00 4f 03 00 00 54 03 00 00 59 03 00 00 5d 03 00 00 61 03 00 00 66 03 00 00 6a 03 00 00 6e 03 00 00 72 03 00 00 76 03 00 00 7a 03 00 00 7e 03 00 00 82 03 00 00 86 03 00 00 89 03 00 00 8d 03 00 00 91 03 00 00 94 03 00 00 98 03 00 00 9b 03 00 00 9e 03 00 00 a2 03 00 00 a5 03 00 00 a8 03 00 00 ab 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b8 03 00 00 bb 03 00 00 be 03 00 00 c1 03 00 00 c3 03 00 00 c6 03 00 00 c9 03 00 00 cc 03 00 00 cf 03 00 00 d1 03 00 00 d4 03 00 00 d7 03 00 00 d9 03 00 00 dc 03 00 00 df 03 00 00 e1 03 00 00 e4 03 00 00 e6 03 00 00 e9 03 00 00 eb 03 00 00 ee 03 00 00 f0 03 00 00 f3 03 00 00 f5 03 00 00 f8 03 00 00 fa 03 00 00 fd 03 00 00 ff 03 00 00]; + data = [00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 19 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 32 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 4b 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 64 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 25 00 00 00 49 00 00 00 6b 00 00 00 8b 00 00 00 a9 00 00 00 c6 00 00 00 e1 00 00 00 f1 00 00 00 01 01 00 00 11 01 00 00 21 01 00 00 30 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 68 01 00 00 75 01 00 00 82 01 00 00 8f 01 00 00 9b 01 00 00 a6 01 00 00 b1 01 00 00 bc 01 00 00 c7 01 00 00 d1 01 00 00 db 01 00 00 e4 01 00 00 ed 01 00 00 f6 01 00 00 fe 01 00 00 06 02 00 00 0d 02 00 00 14 02 00 00 1b 02 00 00 22 02 00 00 29 02 00 00 30 02 00 00 36 02 00 00 3d 02 00 00 44 02 00 00 4b 02 00 00 52 02 00 00 59 02 00 00 5f 02 00 00 66 02 00 00 6d 02 00 00 73 02 00 00 7a 02 00 00 80 02 00 00 87 02 00 00 8d 02 00 00 93 02 00 00 9a 02 00 00 a0 02 00 00 a6 02 00 00 ac 02 00 00 b3 02 00 00 b9 02 00 00 bf 02 00 00 c5 02 00 00 cb 02 00 00 d1 02 00 00 d7 02 00 00 dd 02 00 00 e3 02 00 00 e8 02 00 00 ee 02 00 00 f4 02 00 00 fa 02 00 00 ff 02 00 00 04 03 00 00 09 03 00 00 0e 03 00 00 13 03 00 00 18 03 00 00 1d 03 00 00 21 03 00 00 26 03 00 00 2b 03 00 00 30 03 00 00 35 03 00 00 3a 03 00 00 3e 03 00 00 43 03 00 00 48 03 00 00 4d 03 00 00 51 03 00 00 56 03 00 00 5b 03 00 00 5f 03 00 00 64 03 00 00 68 03 00 00 6d 03 00 00 72 03 00 00 76 03 00 00 7b 03 00 00 7f 03 00 00 84 03 00 00 88 03 00 00 8c 03 00 00 91 03 00 00 95 03 00 00 99 03 00 00 9e 03 00 00 a2 03 00 00 a6 03 00 00 ab 03 00 00 af 03 00 00 b3 03 00 00 b7 03 00 00 bb 03 00 00 bf 03 00 00 c4 03 00 00 c8 03 00 00 cc 03 00 00 d0 03 00 00 d4 03 00 00 d8 03 00 00 dc 03 00 00 e0 03 00 00 e4 03 00 00 e8 03 00 00 eb 03 00 00 ef 03 00 00 f3 03 00 00 f7 03 00 00 fb 03 00 00 ff 03 00 00 07 00 00 00 00 00 00 00 23 00 00 00 44 00 00 00 61 00 00 00 7d 00 00 00 98 00 00 00 b1 00 00 00 c4 00 00 00 d7 00 00 00 e9 00 00 00 fb 00 00 00 0c 01 00 00 1d 01 00 00 2c 01 00 00 3b 01 00 00 49 01 00 00 57 01 00 00 64 01 00 00 72 01 00 00 7f 01 00 00 8c 01 00 00 98 01 00 00 a5 01 00 00 b1 01 00 00 bd 01 00 00 c9 01 00 00 d5 01 00 00 e0 01 00 00 eb 01 00 00 f6 01 00 00 01 02 00 00 0c 02 00 00 16 02 00 00 20 02 00 00 2a 02 00 00 34 02 00 00 3e 02 00 00 48 02 00 00 51 02 00 00 5a 02 00 00 63 02 00 00 6c 02 00 00 75 02 00 00 7e 02 00 00 86 02 00 00 8e 02 00 00 96 02 00 00 9e 02 00 00 a6 02 00 00 ae 02 00 00 b5 02 00 00 bd 02 00 00 c4 02 00 00 cb 02 00 00 d2 02 00 00 d9 02 00 00 e0 02 00 00 e7 02 00 00 ed 02 00 00 f4 02 00 00 fa 02 00 00 00 03 00 00 06 03 00 00 0c 03 00 00 12 03 00 00 18 03 00 00 1d 03 00 00 23 03 00 00 28 03 00 00 2e 03 00 00 33 03 00 00 38 03 00 00 3d 03 00 00 42 03 00 00 47 03 00 00 4c 03 00 00 51 03 00 00 56 03 00 00 5a 03 00 00 5f 03 00 00 63 03 00 00 67 03 00 00 6c 03 00 00 70 03 00 00 74 03 00 00 78 03 00 00 7c 03 00 00 80 03 00 00 84 03 00 00 88 03 00 00 8c 03 00 00 8f 03 00 00 93 03 00 00 97 03 00 00 9a 03 00 00 9e 03 00 00 a1 03 00 00 a5 03 00 00 a8 03 00 00 ab 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b8 03 00 00 bb 03 00 00 bf 03 00 00 c2 03 00 00 c5 03 00 00 c8 03 00 00 cb 03 00 00 ce 03 00 00 d1 03 00 00 d3 03 00 00 d6 03 00 00 d9 03 00 00 dc 03 00 00 df 03 00 00 e2 03 00 00 e4 03 00 00 e7 03 00 00 ea 03 00 00 ed 03 00 00 ef 03 00 00 f2 03 00 00 f5 03 00 00 f7 03 00 00 fa 03 00 00 fc 03 00 00 ff 03 00 00 05 00 00 00 00 00 00 00 2b 00 00 00 50 00 00 00 6a 00 00 00 86 00 00 00 a2 00 00 00 bd 00 00 00 d5 00 00 00 ec 00 00 00 00 01 00 00 11 01 00 00 21 01 00 00 2e 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 6a 01 00 00 78 01 00 00 86 01 00 00 93 01 00 00 a0 01 00 00 ad 01 00 00 ba 01 00 00 c6 01 00 00 d3 01 00 00 df 01 00 00 ea 01 00 00 f6 01 00 00 01 02 00 00 0c 02 00 00 17 02 00 00 22 02 00 00 2c 02 00 00 36 02 00 00 40 02 00 00 4a 02 00 00 54 02 00 00 5d 02 00 00 66 02 00 00 70 02 00 00 78 02 00 00 81 02 00 00 8a 02 00 00 92 02 00 00 9a 02 00 00 a2 02 00 00 aa 02 00 00 b2 02 00 00 ba 02 00 00 c1 02 00 00 c9 02 00 00 d0 02 00 00 d7 02 00 00 de 02 00 00 e5 02 00 00 eb 02 00 00 f2 02 00 00 f8 02 00 00 fe 02 00 00 04 03 00 00 0b 03 00 00 10 03 00 00 16 03 00 00 1c 03 00 00 22 03 00 00 27 03 00 00 2c 03 00 00 32 03 00 00 37 03 00 00 3c 03 00 00 41 03 00 00 46 03 00 00 4b 03 00 00 4f 03 00 00 54 03 00 00 59 03 00 00 5d 03 00 00 61 03 00 00 66 03 00 00 6a 03 00 00 6e 03 00 00 72 03 00 00 76 03 00 00 7a 03 00 00 7e 03 00 00 82 03 00 00 86 03 00 00 89 03 00 00 8d 03 00 00 91 03 00 00 94 03 00 00 98 03 00 00 9b 03 00 00 9e 03 00 00 a2 03 00 00 a5 03 00 00 a8 03 00 00 ab 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b8 03 00 00 bb 03 00 00 be 03 00 00 c1 03 00 00 c3 03 00 00 c6 03 00 00 c9 03 00 00 cc 03 00 00 cf 03 00 00 d1 03 00 00 d4 03 00 00 d7 03 00 00 d9 03 00 00 dc 03 00 00 df 03 00 00 e1 03 00 00 e4 03 00 00 e6 03 00 00 e9 03 00 00 eb 03 00 00 ee 03 00 00 f0 03 00 00 f3 03 00 00 f5 03 00 00 f8 03 00 00 fa 03 00 00 fd 03 00 00 ff 03 00 00]; }; iq_ccm { size = [40 02 00 00]; @@ -35,15 +35,15 @@ }; iq_contrast { size = [b0 00 00 00]; - data = [00 00 00 00 80 00 00 00 00 00 00 00 00 00 8d 28 28 28 28 28 28 28 28 28 87 13 1e 2a 33 35 35 31 25 21 7e 1e 2c 3a 46 4d 4d 46 43 3f 7e 1e 2c 3a 46 53 5d 58 4d 41 7e 1e 2c 3a 46 53 5d 58 4d 41 7e 32 32 32 32 32 32 32 32 32 af 32 32 32 32 32 32 32 32 32 be 00 00 00 00 00 00 00 00 00 80 05 05 05 05 05 05 05 05 05 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00]; + data = [00 00 00 00 80 00 00 00 00 00 00 00 00 00 8d 28 28 28 28 28 28 28 28 28 87 13 1e 2a 33 35 35 31 25 21 87 1e 2c 3a 46 4d 4d 46 43 3f 8d 1e 2c 3a 46 53 5d 58 4d 41 97 1e 2c 3a 46 53 5d 58 4d 41 97 32 32 32 32 32 32 32 32 32 af 32 32 32 32 32 32 32 32 32 be 00 00 00 00 00 00 00 00 00 80 05 05 05 05 05 05 05 05 05 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00]; }; iq_edge { size = [e0 05 00 00]; - data = [01 00 00 00 00 00 00 00 80 00 00 00 31 00 00 00 64 78 8c a0 b4 c8 e0 ff ff e0 c0 aa 9a 90 88 80 1e 30 3c 46 52 55 55 55 58 58 55 4f 49 3f 3f 3c 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 08 00 00 00 28 00 00 00 f0 00 00 00 00 01 00 00 40 50 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 8c 00 00 00 78 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0e 00 00 00 2a 00 00 00 38 00 00 00 46 00 00 00 70 00 00 00 40 6c 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 a0 00 00 00 a0 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 2a 00 00 00 70 00 00 00 7e 00 00 00 92 00 00 00 14 b6 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 a0 00 00 00 a0 00 00 00 02 00 00 00 0f 00 00 00 0c 00 00 00 02 00 00 00 2a 00 00 00 54 00 00 00 70 00 00 00 9a 00 00 00 14 bb 00 00 00 02 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 62 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 66 00 00 00 dc 00 00 00 28 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 88 00 00 00 54 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 70 00 00 00 f0 00 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 01 00 00 00 7e 00 00 00 46 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 5a 00 00 00 5e 01 00 00 88 01 00 00 96 01 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 d2 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 c4 00 00 00 ee 00 00 00 0a 01 00 00 96 01 00 00 14 6a 00 00 00 01 00 00 b4 00 00 00 1c 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 d2 00 00 00 fc 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 46 00 00 00 18 01 00 00 42 01 00 00 5e 01 00 00 14 80 00 00 80 00 00 00 b4 00 00 00 2a 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 0e 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 5a 00 00 00 5a 00 00 00 09 00 00 00 06 00 00 00 04 00 00 00 04 00 00 00 18 01 00 00 5e 01 00 00 7a 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 0f 00 00 00 80 00 00 00 01 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 01 00 00 00 03 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 18 01 00 00 5e 01 00 00 85 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 18 01 00 00 bc 01 00 00 53 02 00 00 5b 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 6e 00 00 00 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 01 00 00 be 01 00 00 58 02 00 00 6c 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00]; + data = [01 00 00 00 00 00 00 00 80 00 00 00 31 00 00 00 64 78 8c a0 b4 c8 e0 ff ff e0 c0 aa 9a 90 88 80 1e 30 3c 46 52 55 55 55 58 58 55 4f 49 3f 3f 3c 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 08 00 00 00 28 00 00 00 f0 00 00 00 00 01 00 00 40 50 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 8c 00 00 00 78 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0e 00 00 00 2a 00 00 00 38 00 00 00 46 00 00 00 70 00 00 00 40 6c 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 82 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 2a 00 00 00 70 00 00 00 7e 00 00 00 92 00 00 00 14 b6 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 78 00 00 00 02 00 00 00 0f 00 00 00 0c 00 00 00 02 00 00 00 2a 00 00 00 54 00 00 00 70 00 00 00 9a 00 00 00 14 bb 00 00 00 02 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 62 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 66 00 00 00 dc 00 00 00 28 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 88 00 00 00 54 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 70 00 00 00 f0 00 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 46 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 5a 00 00 00 5e 01 00 00 88 01 00 00 96 01 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 d2 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 c4 00 00 00 ee 00 00 00 0a 01 00 00 96 01 00 00 14 6a 00 00 00 01 00 00 b4 00 00 00 1c 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 d2 00 00 00 fc 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 46 00 00 00 18 01 00 00 42 01 00 00 5e 01 00 00 14 80 00 00 80 00 00 00 b4 00 00 00 2a 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 0e 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 5a 00 00 00 5a 00 00 00 09 00 00 00 06 00 00 00 04 00 00 00 04 00 00 00 18 01 00 00 5e 01 00 00 7a 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 0f 00 00 00 80 00 00 00 01 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 01 00 00 00 03 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 18 01 00 00 5e 01 00 00 85 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 18 01 00 00 bc 01 00 00 53 02 00 00 5b 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 6e 00 00 00 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 01 00 00 be 01 00 00 58 02 00 00 6c 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00]; }; iq_3dnr { size = [64 1f 00 00]; - data = [01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 40 00 00 00 40 00 00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 c8 00 00 00 c8 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 80 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 b4 00 00 00 e6 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 80 00 00 00 40 00 00 00 00 01 00 00 00 01 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 40 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 04 01 00 00 00 00 00 00 08 00 00 00 50 00 00 00 50 00 00 00 00 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 0f 00 00 00 0e 00 00 00 0e 00 00 00 0f 00 00 00 0d 00 00 00 0d 00 00 00 0d 00 00 00 0d 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 35 00 00 00 35 00 00 00 30 00 00 00 30 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 08 06 04 02 00 00 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 2c 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 50 00 00 00 64 00 00 00 10 00 00 00 04 00 00 00 01 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 29 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 00 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 00 00 00 00 2c 01 00 00 2c 01 00 00 2c 01 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 9d 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 12 00 00 00 11 00 00 00 11 00 00 00 12 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 2d 00 00 00 2d 00 00 00 28 00 00 00 28 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 0a 0a 14 18 0c 05 14 08 02 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 10 00 00 00 f4 01 00 00 64 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 1e 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 00 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 2c 01 00 00 2c 01 00 00 2c 01 00 00 58 02 00 00 58 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 18 01 00 00 18 01 00 00 18 01 00 00 18 01 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 16 00 00 00 15 00 00 00 15 00 00 00 16 00 00 00 14 00 00 00 14 00 00 00 14 00 00 00 14 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 03 03 00 01 00 00 00 14 1e 32 20 18 0c 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 64 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 02 00 00 00 a0 00 00 00 3c 00 00 00 14 00 00 00 03 00 00 00 01 00 00 00 00 00 00 00 0c 00 00 00 16 00 00 00 25 00 00 00 37 00 00 00 4b 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 02 00 00 01 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 cb 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1a 00 00 00 19 00 00 00 19 00 00 00 1a 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 5f 00 00 00 5f 00 00 00 5a 00 00 00 5a 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 14 64 96 28 1e 1e 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 a0 00 00 00 64 00 00 00 18 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 09 00 00 00 19 00 00 00 28 00 00 00 3c 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 a0 00 00 00 a0 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 98 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1e 00 00 00 1d 00 00 00 1d 00 00 00 1e 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 3c 00 00 00 3c 00 00 00 37 00 00 00 37 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 a0 c8 64 32 1e 20 08 02 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 50 00 00 00 64 00 00 00 18 00 00 00 08 00 00 00 03 00 00 00 00 00 00 00 0a 00 00 00 15 00 00 00 25 00 00 00 34 00 00 00 4a 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 3e 00 00 00 48 00 00 00 57 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 d8 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1c 00 00 00 1b 00 00 00 1b 00 00 00 1c 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 4a 01 00 00 40 01 00 00 40 01 00 00 40 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 66 00 00 00 66 00 00 00 61 00 00 00 61 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 b4 c8 80 3c 32 20 08 02 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 40 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 03 00 00 00 64 00 00 00 82 00 00 00 1e 00 00 00 08 00 00 00 04 00 00 00 00 00 00 00 07 00 00 00 10 00 00 00 19 00 00 00 21 00 00 00 29 00 00 00 2f 00 00 00 38 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 15 00 00 00 1e 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 8a 00 00 00 8a 00 00 00 85 00 00 00 85 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 3c 64 82 40 0c 04 40 0c 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 20 03 00 00 2c 01 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 0c 00 00 00 50 00 00 00 78 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0f 00 00 00 19 00 00 00 28 00 00 00 3b 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 62 00 00 00 62 00 00 00 5d 00 00 00 5d 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 3c 64 82 40 0c 04 40 0c 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 0c 00 00 00 50 00 00 00 78 00 00 00 80 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 2c 00 00 00 38 00 00 00 3f 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 21 00 00 00 20 00 00 00 20 00 00 00 21 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 ea 01 00 00 e0 01 00 00 e0 01 00 00 e0 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 46 69 8c 1e 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 09 00 00 00 11 00 00 00 17 00 00 00 1f 00 00 00 27 00 00 00 2d 00 00 00 36 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2c 00 00 00 2b 00 00 00 2b 00 00 00 2c 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 80 02 00 00 76 02 00 00 76 02 00 00 76 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 6e 8c 32 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 08 00 00 00 11 00 00 00 1a 00 00 00 21 00 00 00 27 00 00 00 2f 00 00 00 3a 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2f 00 00 00 2e 00 00 00 2e 00 00 00 2f 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 81 02 00 00 77 02 00 00 77 02 00 00 77 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 b4 78 a0 50 08 04 14 08 02 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 58 02 00 00 58 02 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 07 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 af 00 00 00 03 00 00 00 00 04 00 00 4c 04 00 00 b0 04 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 19 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 23 00 00 00 23 00 00 00 14 00 00 00 14 00 00 00 50 00 00 00 6e 00 00 00 6e 00 00 00 6e 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 a0 00 00 00 3c 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 44 00 00 00 50 00 00 00 50 00 00 00 5a 00 00 00 10 00 00 00 14 00 00 00 03 00 00 00 b4 00 00 00 c8 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 aa 00 00 00 80 00 00 00 40 00 00 00 b8 0b 00 00 70 17 00 00 10 00 00 00 10 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 40 00 00 00 80 00 00 00 ff 00 00 00 10 00 00 00 06 00 00 00 00 00 00 00 06 00 00 00 0d 00 00 00 15 00 00 00 1c 00 00 00 26 00 00 00 2f 00 00 00 3a 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00]; + data = [01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 40 00 00 00 40 00 00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 c8 00 00 00 c8 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 80 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 b4 00 00 00 e6 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 80 00 00 00 40 00 00 00 00 01 00 00 00 01 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 40 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 04 01 00 00 00 00 00 00 08 00 00 00 50 00 00 00 50 00 00 00 00 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 10 00 00 00 0f 00 00 00 0f 00 00 00 10 00 00 00 0e 00 00 00 0e 00 00 00 0e 00 00 00 0e 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 35 00 00 00 35 00 00 00 30 00 00 00 30 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 14 0a 0a 02 00 00 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 2c 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 14 00 00 00 20 00 00 00 04 00 00 00 01 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 29 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 00 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 00 00 00 00 2c 01 00 00 2c 01 00 00 2c 01 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 9d 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 1c 00 00 00 1b 00 00 00 1b 00 00 00 1c 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 2d 00 00 00 2d 00 00 00 28 00 00 00 28 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 0a 0a 14 1e 0c 05 14 08 02 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 10 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 1e 00 00 00 20 00 00 00 06 00 00 00 02 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 01 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 15 00 00 00 15 00 00 00 15 00 00 00 15 00 00 00 d2 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 03 03 00 01 00 00 00 14 50 78 32 50 50 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 ff 00 00 00 ff 00 00 00 30 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 0c 00 00 00 16 00 00 00 25 00 00 00 37 00 00 00 4b 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 02 00 00 01 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 cb 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1a 00 00 00 19 00 00 00 19 00 00 00 1a 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 5f 00 00 00 5f 00 00 00 5a 00 00 00 5a 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 32 64 96 46 64 64 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 0c 00 00 00 19 00 00 00 28 00 00 00 3c 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 a0 00 00 00 a0 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 98 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1e 00 00 00 1d 00 00 00 1d 00 00 00 1e 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 3c 00 00 00 3c 00 00 00 37 00 00 00 37 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 a0 c8 64 78 78 20 08 02 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 0a 00 00 00 15 00 00 00 25 00 00 00 34 00 00 00 4a 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 3e 00 00 00 48 00 00 00 57 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 d8 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1c 00 00 00 1b 00 00 00 1b 00 00 00 1c 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 4a 01 00 00 40 01 00 00 40 01 00 00 40 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 66 00 00 00 66 00 00 00 61 00 00 00 61 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 b4 c8 80 80 80 20 08 02 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 40 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 07 00 00 00 10 00 00 00 19 00 00 00 21 00 00 00 29 00 00 00 2f 00 00 00 38 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 15 00 00 00 1e 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 8a 00 00 00 8a 00 00 00 85 00 00 00 85 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 b4 c8 80 80 80 40 0c 02 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 20 03 00 00 2c 01 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0f 00 00 00 19 00 00 00 28 00 00 00 3b 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 62 00 00 00 62 00 00 00 5d 00 00 00 5d 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 3c 64 82 40 0c 04 40 0c 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 0c 00 00 00 50 00 00 00 78 00 00 00 80 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 2c 00 00 00 38 00 00 00 3f 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 21 00 00 00 20 00 00 00 20 00 00 00 21 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 ea 01 00 00 e0 01 00 00 e0 01 00 00 e0 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 46 69 8c 1e 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 09 00 00 00 11 00 00 00 17 00 00 00 1f 00 00 00 27 00 00 00 2d 00 00 00 36 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2c 00 00 00 2b 00 00 00 2b 00 00 00 2c 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 80 02 00 00 76 02 00 00 76 02 00 00 76 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 6e 8c 32 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 08 00 00 00 11 00 00 00 1a 00 00 00 21 00 00 00 27 00 00 00 2f 00 00 00 3a 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2f 00 00 00 2e 00 00 00 2e 00 00 00 2f 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 81 02 00 00 77 02 00 00 77 02 00 00 77 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 b4 78 a0 50 08 04 14 08 02 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 58 02 00 00 58 02 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 07 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 af 00 00 00 03 00 00 00 00 04 00 00 4c 04 00 00 b0 04 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 19 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 23 00 00 00 23 00 00 00 14 00 00 00 14 00 00 00 50 00 00 00 6e 00 00 00 6e 00 00 00 6e 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 a0 00 00 00 3c 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 44 00 00 00 50 00 00 00 50 00 00 00 5a 00 00 00 10 00 00 00 14 00 00 00 03 00 00 00 b4 00 00 00 c8 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 aa 00 00 00 80 00 00 00 40 00 00 00 b8 0b 00 00 70 17 00 00 10 00 00 00 10 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 40 00 00 00 80 00 00 00 ff 00 00 00 10 00 00 00 06 00 00 00 00 00 00 00 06 00 00 00 0d 00 00 00 15 00 00 00 1c 00 00 00 26 00 00 00 2f 00 00 00 3a 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00]; }; iq_wdr { size = [e4 02 00 00]; diff --git a/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0_cap.dtsi b/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0_cap.dtsi index 798fd5fca..587650660 100755 --- a/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0_cap.dtsi +++ b/rtos/code/hdal/vendor/isp/configs/dtsi/os05b10_iq_0_cap.dtsi @@ -11,7 +11,7 @@ }; iq_nr { size = [f4 12 00 00]; - data = [01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 0b 00 00 00 0c 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 00 00 00 00 0c 00 00 00 80 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 02 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 08 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0c 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 08 00 00 00 09 00 00 00 0a 00 00 00 0b 00 00 00 0c 00 00 00 0d 00 00 00 0e 00 00 00 0f 00 00 00 10 00 00 00 11 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 05 00 00 00 07 00 00 00 09 00 00 00 0a 00 00 00 0e 00 00 00 01 00 00 00 07 00 00 00 0c 00 00 00 11 00 00 00 13 00 00 00 13 00 00 00 0d 00 00 00 0f 00 00 00 10 00 00 00 12 00 00 00 13 00 00 00 14 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 1a 00 00 00 00 00 00 00 0f 00 00 00 16 00 00 00 1b 00 00 00 1f 00 00 00 2c 00 00 00 00 00 00 00 0a 00 00 00 0c 00 00 00 0e 00 00 00 10 00 00 00 12 00 00 00 14 00 00 00 16 00 00 00 17 00 00 00 19 00 00 00 1a 00 00 00 1b 00 00 00 1d 00 00 00 1e 00 00 00 1f 00 00 00 20 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 18 00 00 00 10 00 00 00 18 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 02 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 0d 00 00 00 1b 00 00 00 21 00 00 00 25 00 00 00 29 00 00 00 2d 00 00 00 30 00 00 00 33 00 00 00 35 00 00 00 38 00 00 00 3a 00 00 00 3c 00 00 00 3e 00 00 00 40 00 00 00 42 00 00 00 44 00 00 00 46 00 00 00 00 00 00 00 1e 00 00 00 2a 00 00 00 34 00 00 00 3c 00 00 00 55 00 00 00 00 00 00 00 12 00 00 00 19 00 00 00 1f 00 00 00 24 00 00 00 28 00 00 00 2c 00 00 00 2f 00 00 00 32 00 00 00 36 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 40 00 00 00 43 00 00 00 45 00 00 00 48 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 1d 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 00 00 00 00 0e 00 00 00 14 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 23 00 00 00 26 00 00 00 28 00 00 00 2b 00 00 00 2d 00 00 00 2f 00 00 00 31 00 00 00 33 00 00 00 35 00 00 00 37 00 00 00 39 00 00 00 00 00 00 00 26 00 00 00 36 00 00 00 42 00 00 00 4d 00 00 00 6c 00 00 00 01 00 00 00 47 00 00 00 35 00 00 00 3e 00 00 00 31 00 00 00 37 00 00 00 3c 00 00 00 41 00 00 00 46 00 00 00 4a 00 00 00 4e 00 00 00 51 00 00 00 55 00 00 00 58 00 00 00 5c 00 00 00 5f 00 00 00 62 00 00 00 0f 00 00 00 00 00 00 00 20 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 30 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 55 00 00 00 79 00 00 00 94 00 00 00 ab 00 00 00 f2 00 00 00 00 00 00 00 21 00 00 00 2f 00 00 00 3a 00 00 00 43 00 00 00 4b 00 00 00 52 00 00 00 58 00 00 00 5f 00 00 00 64 00 00 00 6a 00 00 00 6f 00 00 00 74 00 00 00 79 00 00 00 7d 00 00 00 82 00 00 00 86 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 12 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 79 00 00 00 ab 00 00 00 d2 00 00 00 f2 00 00 00 57 01 00 00 00 00 00 00 3a 00 00 00 52 00 00 00 65 00 00 00 74 00 00 00 82 00 00 00 8f 00 00 00 9a 00 00 00 a5 00 00 00 af 00 00 00 b8 00 00 00 c1 00 00 00 ca 00 00 00 d2 00 00 00 da 00 00 00 e2 00 00 00 e9 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 70 00 00 00 9f 00 00 00 c3 00 00 00 e1 00 00 00 3f 01 00 00 00 00 00 00 54 00 00 00 76 00 00 00 91 00 00 00 a8 00 00 00 bb 00 00 00 cd 00 00 00 de 00 00 00 ed 00 00 00 fb 00 00 00 09 01 00 00 16 01 00 00 22 01 00 00 2e 01 00 00 3a 01 00 00 45 01 00 00 50 01 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 09 00 80 00 00 00 00 00 10 00 00 00 16 00 00 00 1c 00 00 00 20 00 00 00 2d 00 00 00 00 00 00 00 12 00 00 00 18 00 00 00 20 00 00 00 25 00 00 00 2a 00 00 00 2e 00 00 00 31 00 00 00 35 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 41 00 00 00 43 00 00 00 46 00 00 00 48 00 00 00 4b 00 00 00 00 00 00 00 1a 01 00 00 8f 01 00 00 e9 01 00 00 34 02 00 00 1e 03 00 00 00 00 00 00 40 00 00 00 5a 00 00 00 6e 00 00 00 80 00 00 00 8f 00 00 00 9c 00 00 00 a9 00 00 00 b5 00 00 00 c0 00 00 00 ca 00 00 00 d4 00 00 00 dd 00 00 00 e6 00 00 00 ef 00 00 00 f7 00 00 00 00 01 00 00 00 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 18 00 00 00 02 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00]; + data = [01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 ff 0f 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 00 00 00 00 0c 00 00 00 80 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 08 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0c 00 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 09 00 00 00 00 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 08 00 00 00 09 00 00 00 0a 00 00 00 0b 00 00 00 0c 00 00 00 0d 00 00 00 0e 00 00 00 0f 00 00 00 10 00 00 00 11 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 00 00 00 00 03 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 08 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 05 00 00 00 07 00 00 00 09 00 00 00 0a 00 00 00 0e 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 10 00 00 00 12 00 00 00 12 00 00 00 0c 00 00 00 0e 00 00 00 0f 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 15 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 00 00 00 00 0f 00 00 00 16 00 00 00 1b 00 00 00 1f 00 00 00 2c 00 00 00 00 00 00 00 0a 00 00 00 0c 00 00 00 0e 00 00 00 10 00 00 00 12 00 00 00 14 00 00 00 16 00 00 00 17 00 00 00 19 00 00 00 1a 00 00 00 1b 00 00 00 1d 00 00 00 1e 00 00 00 1f 00 00 00 20 00 00 00 21 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 18 00 00 00 10 00 00 00 18 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 02 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 00 00 00 00 1a 00 00 00 20 00 00 00 24 00 00 00 28 00 00 00 2c 00 00 00 2f 00 00 00 32 00 00 00 34 00 00 00 37 00 00 00 39 00 00 00 3b 00 00 00 3d 00 00 00 3f 00 00 00 41 00 00 00 43 00 00 00 45 00 00 00 00 00 00 00 1e 00 00 00 2a 00 00 00 34 00 00 00 3c 00 00 00 55 00 00 00 00 00 00 00 12 00 00 00 19 00 00 00 1f 00 00 00 24 00 00 00 28 00 00 00 2c 00 00 00 2f 00 00 00 32 00 00 00 36 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 40 00 00 00 43 00 00 00 45 00 00 00 48 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 1d 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 f7 00 00 00 84 01 00 00 73 03 00 00 e3 0b 00 00 c6 02 00 00 b9 03 00 00 1a 05 00 00 69 08 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 08 00 00 00 0c 00 00 00 0e 00 00 00 11 00 00 00 18 00 00 00 00 00 00 00 0e 00 00 00 14 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 23 00 00 00 26 00 00 00 28 00 00 00 2b 00 00 00 2d 00 00 00 2f 00 00 00 31 00 00 00 33 00 00 00 35 00 00 00 37 00 00 00 39 00 00 00 00 00 00 00 26 00 00 00 36 00 00 00 42 00 00 00 4d 00 00 00 6c 00 00 00 01 00 00 00 47 00 00 00 35 00 00 00 3e 00 00 00 31 00 00 00 37 00 00 00 3c 00 00 00 41 00 00 00 46 00 00 00 4a 00 00 00 4e 00 00 00 51 00 00 00 55 00 00 00 58 00 00 00 5c 00 00 00 5f 00 00 00 62 00 00 00 0f 00 00 00 00 00 00 00 20 00 00 00 0a 00 00 00 30 00 00 00 10 00 00 00 30 00 00 00 00 00 00 00 0f 00 00 00 02 00 00 00 01 00 00 00 00 01 ff 00 00 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 55 00 00 00 79 00 00 00 94 00 00 00 ab 00 00 00 f2 00 00 00 00 00 00 00 21 00 00 00 2f 00 00 00 3a 00 00 00 43 00 00 00 4b 00 00 00 52 00 00 00 58 00 00 00 5f 00 00 00 64 00 00 00 6a 00 00 00 6f 00 00 00 74 00 00 00 79 00 00 00 7d 00 00 00 82 00 00 00 86 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 12 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 79 00 00 00 ab 00 00 00 d2 00 00 00 f2 00 00 00 57 01 00 00 00 00 00 00 3a 00 00 00 52 00 00 00 65 00 00 00 74 00 00 00 82 00 00 00 8f 00 00 00 9a 00 00 00 a5 00 00 00 af 00 00 00 b8 00 00 00 c1 00 00 00 ca 00 00 00 d2 00 00 00 da 00 00 00 e2 00 00 00 e9 00 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 02 00 00 00 00 01 ff 00 01 00 00 00 00 00 00 00 20 00 00 00 96 03 00 00 35 06 00 00 3d 09 00 00 41 0f 00 00 20 00 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 00 00 80 00 00 00 00 00 0d 00 00 00 12 00 00 00 16 00 00 00 1a 00 00 00 25 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 28 00 00 00 2e 00 00 00 33 00 00 00 38 00 00 00 3d 00 00 00 41 00 00 00 45 00 00 00 49 00 00 00 4c 00 00 00 50 00 00 00 53 00 00 00 56 00 00 00 59 00 00 00 5c 00 00 00 00 00 00 00 70 00 00 00 9f 00 00 00 c3 00 00 00 e1 00 00 00 3f 01 00 00 00 00 00 00 54 00 00 00 76 00 00 00 91 00 00 00 a8 00 00 00 bb 00 00 00 cd 00 00 00 de 00 00 00 ed 00 00 00 fb 00 00 00 09 01 00 00 16 01 00 00 22 01 00 00 2e 01 00 00 3a 01 00 00 45 01 00 00 50 01 00 00 0f 00 00 00 00 00 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 16 00 00 00 03 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 c6 02 00 00 0c 04 00 00 af 06 00 00 3d 09 00 00 41 0f 00 00 09 00 80 00 00 00 00 00 10 00 00 00 16 00 00 00 1c 00 00 00 20 00 00 00 2d 00 00 00 00 00 00 00 12 00 00 00 18 00 00 00 20 00 00 00 25 00 00 00 2a 00 00 00 2e 00 00 00 31 00 00 00 35 00 00 00 38 00 00 00 3b 00 00 00 3e 00 00 00 41 00 00 00 43 00 00 00 46 00 00 00 48 00 00 00 4b 00 00 00 00 00 00 00 1a 01 00 00 8f 01 00 00 e9 01 00 00 34 02 00 00 1e 03 00 00 00 00 00 00 40 00 00 00 5a 00 00 00 6e 00 00 00 80 00 00 00 8f 00 00 00 9c 00 00 00 a9 00 00 00 b5 00 00 00 c0 00 00 00 ca 00 00 00 d4 00 00 00 dd 00 00 00 e6 00 00 00 ef 00 00 00 f7 00 00 00 00 01 00 00 00 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 18 00 00 00 02 00 00 00 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 14 02 00 00 03 03 00 00 f8 04 00 00 34 07 00 00 e3 0b 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 9a 01 00 00 53 02 00 00 d6 03 00 00 90 05 00 00 2e 09 00 00 09 00 80 00 00 00 00 00 11 00 00 00 18 00 00 00 1e 00 00 00 23 00 00 00 31 00 00 00 00 00 00 00 30 00 00 00 43 00 00 00 53 00 00 00 60 00 00 00 6b 00 00 00 75 00 00 00 7e 00 00 00 87 00 00 00 90 00 00 00 97 00 00 00 9f 00 00 00 a6 00 00 00 ad 00 00 00 b3 00 00 00 b9 00 00 00 c0 00 00 00 00 00 00 00 8a 00 00 00 c6 00 00 00 f3 00 00 00 17 01 00 00 8c 01 00 00 00 00 00 00 32 00 00 00 47 00 00 00 57 00 00 00 65 00 00 00 71 00 00 00 7c 00 00 00 86 00 00 00 8f 00 00 00 98 00 00 00 a0 00 00 00 a8 00 00 00 af 00 00 00 b7 00 00 00 be 00 00 00 c4 00 00 00 cb 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 00 00 00 00 12 00 00 00 02 00 00 00 02 00 00 00]; }; iq_cfa { size = [54 05 00 00]; @@ -23,7 +23,7 @@ }; iq_gamma { size = [94 0e 00 00]; - data = [00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 19 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 32 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 4b 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 64 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 25 00 00 00 49 00 00 00 6b 00 00 00 8b 00 00 00 a9 00 00 00 c6 00 00 00 e1 00 00 00 f1 00 00 00 01 01 00 00 11 01 00 00 21 01 00 00 30 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 68 01 00 00 75 01 00 00 82 01 00 00 8f 01 00 00 9b 01 00 00 a6 01 00 00 b1 01 00 00 bc 01 00 00 c7 01 00 00 d1 01 00 00 db 01 00 00 e4 01 00 00 ed 01 00 00 f6 01 00 00 fe 01 00 00 06 02 00 00 0d 02 00 00 14 02 00 00 1b 02 00 00 22 02 00 00 29 02 00 00 30 02 00 00 36 02 00 00 3d 02 00 00 44 02 00 00 4b 02 00 00 52 02 00 00 59 02 00 00 5f 02 00 00 66 02 00 00 6d 02 00 00 73 02 00 00 7a 02 00 00 80 02 00 00 87 02 00 00 8d 02 00 00 93 02 00 00 9a 02 00 00 a0 02 00 00 a6 02 00 00 ac 02 00 00 b3 02 00 00 b9 02 00 00 bf 02 00 00 c5 02 00 00 cb 02 00 00 d1 02 00 00 d7 02 00 00 dd 02 00 00 e3 02 00 00 e8 02 00 00 ee 02 00 00 f4 02 00 00 fa 02 00 00 ff 02 00 00 04 03 00 00 09 03 00 00 0e 03 00 00 13 03 00 00 18 03 00 00 1d 03 00 00 21 03 00 00 26 03 00 00 2b 03 00 00 30 03 00 00 35 03 00 00 3a 03 00 00 3e 03 00 00 43 03 00 00 48 03 00 00 4d 03 00 00 51 03 00 00 56 03 00 00 5b 03 00 00 5f 03 00 00 64 03 00 00 68 03 00 00 6d 03 00 00 72 03 00 00 76 03 00 00 7b 03 00 00 7f 03 00 00 84 03 00 00 88 03 00 00 8c 03 00 00 91 03 00 00 95 03 00 00 99 03 00 00 9e 03 00 00 a2 03 00 00 a6 03 00 00 ab 03 00 00 af 03 00 00 b3 03 00 00 b7 03 00 00 bb 03 00 00 bf 03 00 00 c4 03 00 00 c8 03 00 00 cc 03 00 00 d0 03 00 00 d4 03 00 00 d8 03 00 00 dc 03 00 00 e0 03 00 00 e4 03 00 00 e8 03 00 00 eb 03 00 00 ef 03 00 00 f3 03 00 00 f7 03 00 00 fb 03 00 00 ff 03 00 00 07 00 00 00 00 00 00 00 29 00 00 00 53 00 00 00 7e 00 00 00 a5 00 00 00 c6 00 00 00 e5 00 00 00 00 01 00 00 19 01 00 00 2e 01 00 00 41 01 00 00 51 01 00 00 5e 01 00 00 69 01 00 00 76 01 00 00 84 01 00 00 91 01 00 00 9d 01 00 00 aa 01 00 00 b6 01 00 00 c2 01 00 00 cd 01 00 00 d8 01 00 00 e3 01 00 00 ed 01 00 00 f8 01 00 00 01 02 00 00 0b 02 00 00 14 02 00 00 1d 02 00 00 25 02 00 00 2e 02 00 00 36 02 00 00 3e 02 00 00 47 02 00 00 4f 02 00 00 58 02 00 00 60 02 00 00 69 02 00 00 71 02 00 00 79 02 00 00 81 02 00 00 8a 02 00 00 92 02 00 00 9a 02 00 00 a2 02 00 00 aa 02 00 00 b2 02 00 00 ba 02 00 00 c2 02 00 00 c9 02 00 00 d0 02 00 00 d7 02 00 00 de 02 00 00 e4 02 00 00 eb 02 00 00 f2 02 00 00 f8 02 00 00 fe 02 00 00 05 03 00 00 0b 03 00 00 11 03 00 00 17 03 00 00 1c 03 00 00 22 03 00 00 28 03 00 00 2e 03 00 00 33 03 00 00 38 03 00 00 3d 03 00 00 42 03 00 00 47 03 00 00 4c 03 00 00 51 03 00 00 55 03 00 00 5a 03 00 00 5e 03 00 00 63 03 00 00 67 03 00 00 6b 03 00 00 6f 03 00 00 73 03 00 00 77 03 00 00 7b 03 00 00 7f 03 00 00 83 03 00 00 87 03 00 00 8a 03 00 00 8e 03 00 00 92 03 00 00 95 03 00 00 99 03 00 00 9c 03 00 00 9f 03 00 00 a3 03 00 00 a6 03 00 00 a9 03 00 00 ac 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b9 03 00 00 bb 03 00 00 be 03 00 00 c1 03 00 00 c4 03 00 00 c7 03 00 00 ca 03 00 00 cd 03 00 00 cf 03 00 00 d2 03 00 00 d5 03 00 00 d7 03 00 00 da 03 00 00 dc 03 00 00 df 03 00 00 e2 03 00 00 e4 03 00 00 e7 03 00 00 e9 03 00 00 ec 03 00 00 ee 03 00 00 f1 03 00 00 f3 03 00 00 f5 03 00 00 f8 03 00 00 fa 03 00 00 fd 03 00 00 ff 03 00 00 05 00 00 00 00 00 00 00 2b 00 00 00 50 00 00 00 6a 00 00 00 86 00 00 00 a2 00 00 00 bd 00 00 00 d5 00 00 00 ec 00 00 00 00 01 00 00 11 01 00 00 21 01 00 00 2e 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 6a 01 00 00 78 01 00 00 86 01 00 00 93 01 00 00 a0 01 00 00 ad 01 00 00 ba 01 00 00 c6 01 00 00 d3 01 00 00 df 01 00 00 ea 01 00 00 f6 01 00 00 01 02 00 00 0c 02 00 00 17 02 00 00 22 02 00 00 2c 02 00 00 36 02 00 00 40 02 00 00 4a 02 00 00 54 02 00 00 5d 02 00 00 66 02 00 00 70 02 00 00 78 02 00 00 81 02 00 00 8a 02 00 00 92 02 00 00 9a 02 00 00 a2 02 00 00 aa 02 00 00 b2 02 00 00 ba 02 00 00 c1 02 00 00 c9 02 00 00 d0 02 00 00 d7 02 00 00 de 02 00 00 e5 02 00 00 eb 02 00 00 f2 02 00 00 f8 02 00 00 fe 02 00 00 04 03 00 00 0b 03 00 00 10 03 00 00 16 03 00 00 1c 03 00 00 22 03 00 00 27 03 00 00 2c 03 00 00 32 03 00 00 37 03 00 00 3c 03 00 00 41 03 00 00 46 03 00 00 4b 03 00 00 4f 03 00 00 54 03 00 00 59 03 00 00 5d 03 00 00 61 03 00 00 66 03 00 00 6a 03 00 00 6e 03 00 00 72 03 00 00 76 03 00 00 7a 03 00 00 7e 03 00 00 82 03 00 00 86 03 00 00 89 03 00 00 8d 03 00 00 91 03 00 00 94 03 00 00 98 03 00 00 9b 03 00 00 9e 03 00 00 a2 03 00 00 a5 03 00 00 a8 03 00 00 ab 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b8 03 00 00 bb 03 00 00 be 03 00 00 c1 03 00 00 c3 03 00 00 c6 03 00 00 c9 03 00 00 cc 03 00 00 cf 03 00 00 d1 03 00 00 d4 03 00 00 d7 03 00 00 d9 03 00 00 dc 03 00 00 df 03 00 00 e1 03 00 00 e4 03 00 00 e6 03 00 00 e9 03 00 00 eb 03 00 00 ee 03 00 00 f0 03 00 00 f3 03 00 00 f5 03 00 00 f8 03 00 00 fa 03 00 00 fd 03 00 00 ff 03 00 00]; + data = [00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 08 00 00 00 10 00 00 00 18 00 00 00 1c 00 00 00 20 00 00 00 24 00 00 00 26 00 00 00 28 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 19 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 32 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 4b 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 64 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 a0 01 00 00 c0 01 00 00 e0 01 00 00 00 02 00 00 20 02 00 00 40 02 00 00 60 02 00 00 80 02 00 00 a0 02 00 00 c0 02 00 00 e0 02 00 00 00 03 00 00 40 03 00 00 80 03 00 00 c0 03 00 00 00 04 00 00 80 04 00 00 00 05 00 00 80 05 00 00 00 06 00 00 80 06 00 00 00 07 00 00 80 07 00 00 00 08 00 00 80 08 00 00 00 09 00 00 80 09 00 00 00 0a 00 00 80 0a 00 00 00 0b 00 00 80 0b 00 00 00 0c 00 00 80 0c 00 00 00 0d 00 00 80 0d 00 00 00 0e 00 00 80 0e 00 00 00 0f 00 00 80 0f 00 00 ff 0f 00 00 00 00 00 00 25 00 00 00 49 00 00 00 6b 00 00 00 8b 00 00 00 a9 00 00 00 c6 00 00 00 e1 00 00 00 f1 00 00 00 01 01 00 00 11 01 00 00 21 01 00 00 30 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 68 01 00 00 75 01 00 00 82 01 00 00 8f 01 00 00 9b 01 00 00 a6 01 00 00 b1 01 00 00 bc 01 00 00 c7 01 00 00 d1 01 00 00 db 01 00 00 e4 01 00 00 ed 01 00 00 f6 01 00 00 fe 01 00 00 06 02 00 00 0d 02 00 00 14 02 00 00 1b 02 00 00 22 02 00 00 29 02 00 00 30 02 00 00 36 02 00 00 3d 02 00 00 44 02 00 00 4b 02 00 00 52 02 00 00 59 02 00 00 5f 02 00 00 66 02 00 00 6d 02 00 00 73 02 00 00 7a 02 00 00 80 02 00 00 87 02 00 00 8d 02 00 00 93 02 00 00 9a 02 00 00 a0 02 00 00 a6 02 00 00 ac 02 00 00 b3 02 00 00 b9 02 00 00 bf 02 00 00 c5 02 00 00 cb 02 00 00 d1 02 00 00 d7 02 00 00 dd 02 00 00 e3 02 00 00 e8 02 00 00 ee 02 00 00 f4 02 00 00 fa 02 00 00 ff 02 00 00 04 03 00 00 09 03 00 00 0e 03 00 00 13 03 00 00 18 03 00 00 1d 03 00 00 21 03 00 00 26 03 00 00 2b 03 00 00 30 03 00 00 35 03 00 00 3a 03 00 00 3e 03 00 00 43 03 00 00 48 03 00 00 4d 03 00 00 51 03 00 00 56 03 00 00 5b 03 00 00 5f 03 00 00 64 03 00 00 68 03 00 00 6d 03 00 00 72 03 00 00 76 03 00 00 7b 03 00 00 7f 03 00 00 84 03 00 00 88 03 00 00 8c 03 00 00 91 03 00 00 95 03 00 00 99 03 00 00 9e 03 00 00 a2 03 00 00 a6 03 00 00 ab 03 00 00 af 03 00 00 b3 03 00 00 b7 03 00 00 bb 03 00 00 bf 03 00 00 c4 03 00 00 c8 03 00 00 cc 03 00 00 d0 03 00 00 d4 03 00 00 d8 03 00 00 dc 03 00 00 e0 03 00 00 e4 03 00 00 e8 03 00 00 eb 03 00 00 ef 03 00 00 f3 03 00 00 f7 03 00 00 fb 03 00 00 ff 03 00 00 07 00 00 00 00 00 00 00 23 00 00 00 44 00 00 00 61 00 00 00 7d 00 00 00 98 00 00 00 b1 00 00 00 c4 00 00 00 d7 00 00 00 e9 00 00 00 fb 00 00 00 0c 01 00 00 1d 01 00 00 2c 01 00 00 3b 01 00 00 49 01 00 00 57 01 00 00 64 01 00 00 72 01 00 00 7f 01 00 00 8c 01 00 00 98 01 00 00 a5 01 00 00 b1 01 00 00 bd 01 00 00 c9 01 00 00 d5 01 00 00 e0 01 00 00 eb 01 00 00 f6 01 00 00 01 02 00 00 0c 02 00 00 16 02 00 00 20 02 00 00 2a 02 00 00 34 02 00 00 3e 02 00 00 48 02 00 00 51 02 00 00 5a 02 00 00 63 02 00 00 6c 02 00 00 75 02 00 00 7e 02 00 00 86 02 00 00 8e 02 00 00 96 02 00 00 9e 02 00 00 a6 02 00 00 ae 02 00 00 b5 02 00 00 bd 02 00 00 c4 02 00 00 cb 02 00 00 d2 02 00 00 d9 02 00 00 e0 02 00 00 e7 02 00 00 ed 02 00 00 f4 02 00 00 fa 02 00 00 00 03 00 00 06 03 00 00 0c 03 00 00 12 03 00 00 18 03 00 00 1d 03 00 00 23 03 00 00 28 03 00 00 2e 03 00 00 33 03 00 00 38 03 00 00 3d 03 00 00 42 03 00 00 47 03 00 00 4c 03 00 00 51 03 00 00 56 03 00 00 5a 03 00 00 5f 03 00 00 63 03 00 00 67 03 00 00 6c 03 00 00 70 03 00 00 74 03 00 00 78 03 00 00 7c 03 00 00 80 03 00 00 84 03 00 00 88 03 00 00 8c 03 00 00 8f 03 00 00 93 03 00 00 97 03 00 00 9a 03 00 00 9e 03 00 00 a1 03 00 00 a5 03 00 00 a8 03 00 00 ab 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b8 03 00 00 bb 03 00 00 bf 03 00 00 c2 03 00 00 c5 03 00 00 c8 03 00 00 cb 03 00 00 ce 03 00 00 d1 03 00 00 d3 03 00 00 d6 03 00 00 d9 03 00 00 dc 03 00 00 df 03 00 00 e2 03 00 00 e4 03 00 00 e7 03 00 00 ea 03 00 00 ed 03 00 00 ef 03 00 00 f2 03 00 00 f5 03 00 00 f7 03 00 00 fa 03 00 00 fc 03 00 00 ff 03 00 00 05 00 00 00 00 00 00 00 2b 00 00 00 50 00 00 00 6a 00 00 00 86 00 00 00 a2 00 00 00 bd 00 00 00 d5 00 00 00 ec 00 00 00 00 01 00 00 11 01 00 00 21 01 00 00 2e 01 00 00 3e 01 00 00 4d 01 00 00 5b 01 00 00 6a 01 00 00 78 01 00 00 86 01 00 00 93 01 00 00 a0 01 00 00 ad 01 00 00 ba 01 00 00 c6 01 00 00 d3 01 00 00 df 01 00 00 ea 01 00 00 f6 01 00 00 01 02 00 00 0c 02 00 00 17 02 00 00 22 02 00 00 2c 02 00 00 36 02 00 00 40 02 00 00 4a 02 00 00 54 02 00 00 5d 02 00 00 66 02 00 00 70 02 00 00 78 02 00 00 81 02 00 00 8a 02 00 00 92 02 00 00 9a 02 00 00 a2 02 00 00 aa 02 00 00 b2 02 00 00 ba 02 00 00 c1 02 00 00 c9 02 00 00 d0 02 00 00 d7 02 00 00 de 02 00 00 e5 02 00 00 eb 02 00 00 f2 02 00 00 f8 02 00 00 fe 02 00 00 04 03 00 00 0b 03 00 00 10 03 00 00 16 03 00 00 1c 03 00 00 22 03 00 00 27 03 00 00 2c 03 00 00 32 03 00 00 37 03 00 00 3c 03 00 00 41 03 00 00 46 03 00 00 4b 03 00 00 4f 03 00 00 54 03 00 00 59 03 00 00 5d 03 00 00 61 03 00 00 66 03 00 00 6a 03 00 00 6e 03 00 00 72 03 00 00 76 03 00 00 7a 03 00 00 7e 03 00 00 82 03 00 00 86 03 00 00 89 03 00 00 8d 03 00 00 91 03 00 00 94 03 00 00 98 03 00 00 9b 03 00 00 9e 03 00 00 a2 03 00 00 a5 03 00 00 a8 03 00 00 ab 03 00 00 af 03 00 00 b2 03 00 00 b5 03 00 00 b8 03 00 00 bb 03 00 00 be 03 00 00 c1 03 00 00 c3 03 00 00 c6 03 00 00 c9 03 00 00 cc 03 00 00 cf 03 00 00 d1 03 00 00 d4 03 00 00 d7 03 00 00 d9 03 00 00 dc 03 00 00 df 03 00 00 e1 03 00 00 e4 03 00 00 e6 03 00 00 e9 03 00 00 eb 03 00 00 ee 03 00 00 f0 03 00 00 f3 03 00 00 f5 03 00 00 f8 03 00 00 fa 03 00 00 fd 03 00 00 ff 03 00 00]; }; iq_ccm { size = [40 02 00 00]; @@ -35,19 +35,19 @@ }; iq_contrast { size = [b0 00 00 00]; - data = [00 00 00 00 80 00 00 00 00 00 00 00 00 00 8d 1e 1e 1e 1e 1e 1e 1e 1e 1e 87 25 25 25 25 25 25 25 25 25 87 28 28 28 28 28 28 28 28 28 87 28 28 28 28 28 28 28 28 28 7e 28 28 28 28 28 28 28 28 28 7e 28 28 28 28 28 28 28 28 28 af 28 28 28 28 28 28 28 28 28 be 00 00 00 00 00 00 00 00 00 80 05 05 05 05 05 05 05 05 05 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00]; + data = [00 00 00 00 80 00 00 00 00 00 00 00 00 00 8d 28 28 28 28 28 28 28 28 28 87 13 1e 2a 33 35 35 31 25 21 87 1e 2c 3a 46 4d 4d 46 43 3f 8d 1e 2c 3a 46 53 5d 58 4d 41 97 1e 2c 3a 46 53 5d 58 4d 41 97 32 32 32 32 32 32 32 32 32 af 32 32 32 32 32 32 32 32 32 be 00 00 00 00 00 00 00 00 00 80 05 05 05 05 05 05 05 05 05 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 0a 0a 0a 0a 0a 0a 0a 0a 0a 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00]; }; iq_edge { size = [e0 05 00 00]; - data = [01 00 00 00 00 00 00 00 80 00 00 00 31 00 00 00 64 78 8c a0 b4 c8 e0 ff ff e0 c0 aa 9a 90 88 80 1e 30 3c 46 52 55 55 55 58 58 55 4f 49 3f 3f 3c 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 40 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 08 00 00 00 28 00 00 00 f0 00 00 00 00 01 00 00 40 50 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 86 00 00 00 85 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0e 00 00 00 2a 00 00 00 38 00 00 00 46 00 00 00 70 00 00 00 40 6c 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 82 00 00 00 78 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 2a 00 00 00 70 00 00 00 7e 00 00 00 92 00 00 00 28 5a 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 82 00 00 00 73 00 00 00 02 00 00 00 0f 00 00 00 0c 00 00 00 02 00 00 00 2a 00 00 00 54 00 00 00 70 00 00 00 9a 00 00 00 28 60 00 00 00 02 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 82 00 00 00 73 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 66 00 00 00 dc 00 00 00 28 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 54 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 70 00 00 00 f0 00 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 01 00 00 00 7e 00 00 00 46 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 5a 00 00 00 5e 01 00 00 88 01 00 00 96 01 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 d2 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 c4 00 00 00 ee 00 00 00 0a 01 00 00 96 01 00 00 14 6a 00 00 00 01 00 00 b4 00 00 00 1c 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 d2 00 00 00 fc 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 46 00 00 00 18 01 00 00 42 01 00 00 5e 01 00 00 14 80 00 00 80 00 00 00 b4 00 00 00 2a 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 0e 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 5a 00 00 00 5a 00 00 00 09 00 00 00 06 00 00 00 04 00 00 00 04 00 00 00 18 01 00 00 5e 01 00 00 7a 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 0f 00 00 00 80 00 00 00 01 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 01 00 00 00 03 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 18 01 00 00 5e 01 00 00 85 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 18 01 00 00 bc 01 00 00 53 02 00 00 5b 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 6e 00 00 00 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 01 00 00 be 01 00 00 58 02 00 00 6c 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00]; + data = [01 00 00 00 00 00 00 00 80 00 00 00 31 00 00 00 64 78 8c a0 b4 c8 e0 ff ff e0 c0 aa 9a 90 88 80 1e 30 3c 46 52 55 55 55 58 58 55 4f 49 3f 3f 3c 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 08 00 00 00 28 00 00 00 f0 00 00 00 00 01 00 00 40 50 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 8c 00 00 00 78 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0e 00 00 00 2a 00 00 00 38 00 00 00 46 00 00 00 70 00 00 00 40 6c 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 82 00 00 00 10 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 2a 00 00 00 70 00 00 00 7e 00 00 00 92 00 00 00 14 b6 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 78 00 00 00 02 00 00 00 0f 00 00 00 0c 00 00 00 02 00 00 00 2a 00 00 00 54 00 00 00 70 00 00 00 9a 00 00 00 14 bb 00 00 00 02 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 8c 00 00 00 62 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 66 00 00 00 dc 00 00 00 28 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 88 00 00 00 54 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 54 00 00 00 62 00 00 00 70 00 00 00 f0 00 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 46 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 5a 00 00 00 5e 01 00 00 88 01 00 00 96 01 00 00 18 60 00 00 00 01 00 00 b4 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 02 00 00 00 7e 00 00 00 d2 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 c4 00 00 00 ee 00 00 00 0a 01 00 00 96 01 00 00 14 6a 00 00 00 01 00 00 b4 00 00 00 1c 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 d2 00 00 00 fc 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 46 00 00 00 18 01 00 00 42 01 00 00 5e 01 00 00 14 80 00 00 80 00 00 00 b4 00 00 00 2a 00 00 00 80 00 00 00 00 00 00 00 02 00 00 00 0e 00 00 00 00 02 00 00 01 00 00 00 02 00 00 00 5a 00 00 00 5a 00 00 00 09 00 00 00 06 00 00 00 04 00 00 00 04 00 00 00 18 01 00 00 5e 01 00 00 7a 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 0f 00 00 00 80 00 00 00 01 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 01 00 00 00 03 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 18 01 00 00 5e 01 00 00 85 01 00 00 8f 01 00 00 20 50 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 0a 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 5a 00 00 00 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 18 01 00 00 bc 01 00 00 53 02 00 00 5b 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 19 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 6e 00 00 00 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 01 00 00 be 01 00 00 58 02 00 00 6c 02 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00 60 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 88 00 00 00 a8 00 00 00 33 01 00 00 43 01 00 00 20 46 00 00 00 01 00 00 00 01 00 00 00 00 00 00 80 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 05 00 00 00]; }; iq_3dnr { size = [64 1f 00 00]; - data = [01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 40 00 00 00 40 00 00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 c8 00 00 00 c8 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 80 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 b4 00 00 00 e6 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 80 00 00 00 40 00 00 00 00 01 00 00 00 01 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 40 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 04 01 00 00 00 00 00 00 08 00 00 00 50 00 00 00 50 00 00 00 00 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 0f 00 00 00 0e 00 00 00 0e 00 00 00 0f 00 00 00 0d 00 00 00 0d 00 00 00 0d 00 00 00 0d 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 35 00 00 00 35 00 00 00 30 00 00 00 30 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 08 06 04 02 00 00 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 2c 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 50 00 00 00 64 00 00 00 10 00 00 00 04 00 00 00 01 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 29 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 00 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 00 00 00 00 2c 01 00 00 2c 01 00 00 2c 01 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 9d 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 12 00 00 00 11 00 00 00 11 00 00 00 12 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 2d 00 00 00 2d 00 00 00 28 00 00 00 28 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 02 0a 14 12 0a 05 14 08 02 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 10 00 00 00 2c 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 1e 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 00 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 2c 01 00 00 2c 01 00 00 2c 01 00 00 58 02 00 00 58 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 18 01 00 00 18 01 00 00 18 01 00 00 18 01 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 16 00 00 00 15 00 00 00 15 00 00 00 16 00 00 00 14 00 00 00 14 00 00 00 14 00 00 00 14 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 03 03 00 01 00 00 00 05 1e 32 1c 14 0c 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 02 00 00 00 64 00 00 00 3c 00 00 00 14 00 00 00 03 00 00 00 01 00 00 00 00 00 00 00 0c 00 00 00 16 00 00 00 25 00 00 00 37 00 00 00 4b 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 02 00 00 01 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 cb 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1a 00 00 00 19 00 00 00 19 00 00 00 1a 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 5f 00 00 00 5f 00 00 00 5a 00 00 00 5a 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 14 64 96 28 1e 1e 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 50 00 00 00 64 00 00 00 18 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 09 00 00 00 19 00 00 00 28 00 00 00 3c 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 a0 00 00 00 a0 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 98 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1e 00 00 00 1d 00 00 00 1d 00 00 00 1e 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 3c 00 00 00 3c 00 00 00 37 00 00 00 37 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 a0 c8 64 32 1e 20 08 02 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 50 00 00 00 64 00 00 00 18 00 00 00 08 00 00 00 03 00 00 00 00 00 00 00 0a 00 00 00 15 00 00 00 25 00 00 00 34 00 00 00 4a 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 3e 00 00 00 48 00 00 00 57 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 d8 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1c 00 00 00 1b 00 00 00 1b 00 00 00 1c 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 4a 01 00 00 40 01 00 00 40 01 00 00 40 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 66 00 00 00 66 00 00 00 61 00 00 00 61 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 b4 c8 80 3c 32 20 08 02 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 40 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 03 00 00 00 64 00 00 00 82 00 00 00 1e 00 00 00 08 00 00 00 04 00 00 00 00 00 00 00 07 00 00 00 10 00 00 00 19 00 00 00 21 00 00 00 29 00 00 00 2f 00 00 00 38 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 15 00 00 00 1e 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 8a 00 00 00 8a 00 00 00 85 00 00 00 85 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 3c 64 82 40 0c 04 40 0c 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 20 03 00 00 2c 01 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 0c 00 00 00 50 00 00 00 78 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0f 00 00 00 19 00 00 00 28 00 00 00 3b 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 62 00 00 00 62 00 00 00 5d 00 00 00 5d 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 3c 64 82 40 0c 04 40 0c 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 0c 00 00 00 50 00 00 00 78 00 00 00 80 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 2c 00 00 00 38 00 00 00 3f 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 21 00 00 00 20 00 00 00 20 00 00 00 21 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 ea 01 00 00 e0 01 00 00 e0 01 00 00 e0 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 46 69 8c 1e 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 09 00 00 00 11 00 00 00 17 00 00 00 1f 00 00 00 27 00 00 00 2d 00 00 00 36 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2c 00 00 00 2b 00 00 00 2b 00 00 00 2c 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 80 02 00 00 76 02 00 00 76 02 00 00 76 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 6e 8c 32 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 08 00 00 00 11 00 00 00 1a 00 00 00 21 00 00 00 27 00 00 00 2f 00 00 00 3a 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2f 00 00 00 2e 00 00 00 2e 00 00 00 2f 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 81 02 00 00 77 02 00 00 77 02 00 00 77 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 b4 78 a0 50 08 04 14 08 02 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 58 02 00 00 58 02 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 07 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 af 00 00 00 03 00 00 00 00 04 00 00 4c 04 00 00 b0 04 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 19 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 23 00 00 00 23 00 00 00 14 00 00 00 14 00 00 00 50 00 00 00 6e 00 00 00 6e 00 00 00 6e 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 a0 00 00 00 3c 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 44 00 00 00 50 00 00 00 50 00 00 00 5a 00 00 00 10 00 00 00 14 00 00 00 03 00 00 00 b4 00 00 00 c8 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 aa 00 00 00 80 00 00 00 40 00 00 00 b8 0b 00 00 70 17 00 00 10 00 00 00 10 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 40 00 00 00 80 00 00 00 ff 00 00 00 10 00 00 00 06 00 00 00 00 00 00 00 06 00 00 00 0d 00 00 00 15 00 00 00 1c 00 00 00 26 00 00 00 2f 00 00 00 3a 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00]; + data = [01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 40 00 00 00 40 00 00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 c8 00 00 00 c8 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 05 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 08 00 00 00 80 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 b4 00 00 00 e6 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 80 00 00 00 40 00 00 00 00 01 00 00 00 01 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 10 00 00 00 40 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 00 00 00 00 06 00 00 00 0c 00 00 00 18 00 00 00 28 00 00 00 4c 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 40 00 00 00 04 01 00 00 00 00 00 00 08 00 00 00 50 00 00 00 50 00 00 00 00 00 00 00 b4 00 00 00 b4 00 00 00 b4 00 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 10 00 00 00 0f 00 00 00 0f 00 00 00 10 00 00 00 0e 00 00 00 0e 00 00 00 0e 00 00 00 0e 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 35 00 00 00 35 00 00 00 30 00 00 00 30 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 2b 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 14 0a 0a 02 00 00 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 08 00 00 00 2c 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 14 00 00 00 20 00 00 00 04 00 00 00 01 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 29 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 00 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 00 00 00 00 2c 01 00 00 2c 01 00 00 2c 01 00 00 f4 01 00 00 f4 01 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 9d 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 8c 00 00 00 1c 00 00 00 1b 00 00 00 1b 00 00 00 1c 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 82 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 78 00 00 00 2d 00 00 00 2d 00 00 00 28 00 00 00 28 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 23 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 0a 0a 14 1e 0c 05 14 08 02 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 10 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 0f 00 00 00 1e 00 00 00 20 00 00 00 06 00 00 00 02 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 01 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 b4 00 00 00 08 00 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 17 00 00 00 15 00 00 00 15 00 00 00 15 00 00 00 15 00 00 00 d2 00 00 00 c8 00 00 00 c8 00 00 00 c8 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 be 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 3a 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 03 03 00 01 00 00 00 14 50 78 32 50 50 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 ff 00 00 00 ff 00 00 00 30 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 0c 00 00 00 16 00 00 00 25 00 00 00 37 00 00 00 4b 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 02 00 00 01 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 cb 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1a 00 00 00 19 00 00 00 19 00 00 00 1a 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 5f 00 00 00 5f 00 00 00 5a 00 00 00 5a 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 55 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 32 64 96 46 64 64 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 0c 00 00 00 19 00 00 00 28 00 00 00 3c 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 a0 00 00 00 a0 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 84 03 00 00 84 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 98 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1e 00 00 00 1d 00 00 00 1d 00 00 00 1e 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 1c 00 00 00 18 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 04 01 00 00 3c 00 00 00 3c 00 00 00 37 00 00 00 37 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 a0 c8 64 78 78 20 08 02 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 50 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 0a 00 00 00 15 00 00 00 25 00 00 00 34 00 00 00 4a 00 00 00 60 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 20 00 00 00 30 00 00 00 3e 00 00 00 48 00 00 00 57 00 00 00 70 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 02 00 00 00 08 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 d8 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 1c 00 00 00 1b 00 00 00 1b 00 00 00 1c 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 1a 00 00 00 4a 01 00 00 40 01 00 00 40 01 00 00 40 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 36 01 00 00 66 00 00 00 66 00 00 00 61 00 00 00 61 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 5c 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 b4 c8 80 80 80 20 08 02 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 f4 01 00 00 c8 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 64 00 00 00 64 00 00 00 40 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 0c 00 00 00 06 00 00 00 00 00 00 00 07 00 00 00 10 00 00 00 19 00 00 00 21 00 00 00 29 00 00 00 2f 00 00 00 38 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0d 00 00 00 15 00 00 00 1e 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 5e 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 22 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 8a 00 00 00 8a 00 00 00 85 00 00 00 85 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 b4 c8 80 80 80 40 0c 02 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 20 03 00 00 2c 01 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 05 00 00 00 ff 00 00 00 ff 00 00 00 40 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 06 00 00 00 0f 00 00 00 19 00 00 00 28 00 00 00 3b 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 2c 01 00 00 2c 01 00 00 00 00 00 00 f4 01 00 00 f4 01 00 00 f4 01 00 00 e8 03 00 00 e8 03 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 c3 00 00 00 08 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 28 00 00 00 27 00 00 00 27 00 00 00 28 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 26 00 00 00 90 01 00 00 86 01 00 00 86 01 00 00 86 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 7c 01 00 00 62 00 00 00 62 00 00 00 5d 00 00 00 5d 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 58 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 3c 64 82 40 0c 04 40 0c 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 0c 00 00 00 50 00 00 00 78 00 00 00 80 00 00 00 10 00 00 00 08 00 00 00 00 00 00 00 0d 00 00 00 1b 00 00 00 2c 00 00 00 38 00 00 00 3f 00 00 00 45 00 00 00 4b 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 20 03 00 00 20 03 00 00 03 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 21 00 00 00 20 00 00 00 20 00 00 00 21 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 1f 00 00 00 ea 01 00 00 e0 01 00 00 e0 01 00 00 e0 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 d6 01 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 46 69 8c 1e 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 09 00 00 00 11 00 00 00 17 00 00 00 1f 00 00 00 27 00 00 00 2d 00 00 00 36 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2c 00 00 00 2b 00 00 00 2b 00 00 00 2c 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 2a 00 00 00 80 02 00 00 76 02 00 00 76 02 00 00 76 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 6c 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 64 6e 8c 32 08 04 14 08 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 64 00 00 00 30 00 00 00 00 00 00 00 08 00 00 00 11 00 00 00 1a 00 00 00 21 00 00 00 27 00 00 00 2f 00 00 00 3a 00 00 00 64 00 00 00 30 00 00 00 02 01 00 00 03 00 00 00 08 00 00 00 96 00 00 00 96 00 00 00 00 00 00 00 dc 00 00 00 dc 00 00 00 dc 00 00 00 84 03 00 00 84 03 00 00 02 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 07 00 00 00 07 00 00 00 08 00 00 00 80 00 00 00 07 00 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 4a 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 0e 01 00 00 2f 00 00 00 2e 00 00 00 2e 00 00 00 2f 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 2d 00 00 00 81 02 00 00 77 02 00 00 77 02 00 00 77 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 6d 02 00 00 49 00 00 00 49 00 00 00 44 00 00 00 44 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 3f 00 00 00 08 00 00 00 10 00 00 00 04 00 00 00 10 00 00 00 14 00 00 00 06 00 00 00 01 01 01 00 01 00 00 00 b4 78 a0 50 08 04 14 08 02 00 00 00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00 00 40 00 00 00 20 00 00 00 e8 03 00 00 e8 03 00 00 08 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 3c 00 00 00 6e 00 00 00 64 00 00 00 20 00 00 00 10 00 00 00 00 00 00 00 07 00 00 00 0c 00 00 00 15 00 00 00 1e 00 00 00 26 00 00 00 2c 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 0b 00 00 00 13 00 00 00 1c 00 00 00 23 00 00 00 29 00 00 00 31 00 00 00 3c 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 c8 00 00 00 c8 00 00 00 00 00 00 00 90 01 00 00 90 01 00 00 90 01 00 00 58 02 00 00 58 02 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 07 00 00 00 05 00 00 00 05 00 00 00 05 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 00 af 00 00 00 03 00 00 00 00 04 00 00 4c 04 00 00 b0 04 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 14 05 00 00 19 00 00 00 32 00 00 00 32 00 00 00 32 00 00 00 23 00 00 00 23 00 00 00 14 00 00 00 14 00 00 00 50 00 00 00 6e 00 00 00 6e 00 00 00 6e 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 a0 00 00 00 3c 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 44 00 00 00 50 00 00 00 50 00 00 00 5a 00 00 00 10 00 00 00 14 00 00 00 03 00 00 00 b4 00 00 00 c8 00 00 00 04 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8c 00 00 00 96 00 00 00 a0 00 00 00 aa 00 00 00 80 00 00 00 40 00 00 00 b8 0b 00 00 70 17 00 00 10 00 00 00 10 00 00 00 20 00 00 00 20 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 40 00 00 00 80 00 00 00 ff 00 00 00 10 00 00 00 06 00 00 00 00 00 00 00 06 00 00 00 0d 00 00 00 15 00 00 00 1c 00 00 00 26 00 00 00 2f 00 00 00 3a 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00 00 00 00 00 0f 00 00 00 80 00 00 00 80 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 04 00 00 00 04 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 08 00 00 00 09 00 00 00 09 00 00 00 0a 00 00 00 0a 00 00 00 0a 00 00 00 0b 00 00 00 0b 00 00 00 96 00 00 00 03 00 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 18 00 00 00 18 00 00 00 17 00 00 00 15 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 16 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 5a 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 3c 00 00 00 08 00 00 00 10 00 00 00 14 00 00 00 b4 00 00 00 e6 00 00 00 02 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 6e 00 00 00 78 00 00 00 82 00 00 00 80 00 00 00 40 00 00 00 b0 04 00 00 d0 07 00 00 14 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 14 00 00 00 18 00 00 00 18 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 20 00 00 00 80 00 00 00 ff 00 00 00 20 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 40 00 00 00 20 00 00 00 00 00 00 00 06 00 00 00 0b 00 00 00 0b 00 00 00 13 00 00 00 18 00 00 00 21 00 00 00 34 00 00 00 40 00 00 00 20 00 00 00 04 01 00 00]; }; iq_wdr { size = [e4 02 00 00]; - data = [01 00 00 00 00 00 00 00 20 00 00 00 12 00 00 00 80 00 00 00 05 00 00 00 03 00 00 00 00 00 00 00 01 00 00 00 03 00 00 00 07 00 00 00 0f 00 00 00 17 00 00 00 1f 00 00 00 23 00 00 00 27 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 0f 00 00 e6 0f 00 00 a6 0f 00 00 29 0f 00 00 cf 0e 00 00 64 0e 00 00 e8 0d 00 00 5e 0d 00 00 14 0d 00 00 c7 0c 00 00 78 0c 00 00 27 0c 00 00 d5 0b 00 00 81 0b 00 00 2e 0b 00 00 da 0a 00 00 86 0a 00 00 33 0a 00 00 e1 09 00 00 90 09 00 00 41 09 00 00 f3 08 00 00 a7 08 00 00 5e 08 00 00 16 08 00 00 d1 07 00 00 8e 07 00 00 4d 07 00 00 0f 07 00 00 d3 06 00 00 99 06 00 00 62 06 00 00 fb 05 00 00 9c 05 00 00 46 05 00 00 f8 04 00 00 b0 04 00 00 70 04 00 00 35 04 00 00 00 04 00 00 a4 03 00 00 57 03 00 00 e4 02 00 00 94 02 00 00 5b 02 00 00 31 02 00 00 12 02 00 00 fb 01 00 00 e9 01 00 00 dc 01 00 00 d1 01 00 00 c8 01 00 00 c1 01 00 00 bb 01 00 00 b7 01 00 00 b3 01 00 00 b0 01 00 00 ad 01 00 00 ab 01 00 00 a9 01 00 00 a7 01 00 00 a6 01 00 00 a4 01 00 00 a3 01 00 00 a2 01 00 00 20 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 30 00 00 00 00 00 00 00 ff 00 00 00 30 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00]; + data = [01 00 00 00 00 00 00 00 20 00 00 00 12 00 00 00 80 00 00 00 05 00 00 00 03 00 00 00 00 00 00 00 01 00 00 00 03 00 00 00 07 00 00 00 0f 00 00 00 17 00 00 00 1f 00 00 00 23 00 00 00 27 00 00 00 29 00 00 00 2a 00 00 00 2b 00 00 00 2c 00 00 00 2d 00 00 00 2e 00 00 00 2f 00 00 00 30 00 00 00 31 00 00 00 32 00 00 00 33 00 00 00 34 00 00 00 35 00 00 00 36 00 00 00 37 00 00 00 38 00 00 00 39 00 00 00 3a 00 00 00 3b 00 00 00 3c 00 00 00 3d 00 00 00 3e 00 00 00 3f 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 0f 00 00 e6 0f 00 00 a6 0f 00 00 29 0f 00 00 cf 0e 00 00 64 0e 00 00 e8 0d 00 00 5e 0d 00 00 14 0d 00 00 c7 0c 00 00 78 0c 00 00 27 0c 00 00 d5 0b 00 00 81 0b 00 00 2e 0b 00 00 da 0a 00 00 86 0a 00 00 33 0a 00 00 e1 09 00 00 90 09 00 00 41 09 00 00 f3 08 00 00 a7 08 00 00 5e 08 00 00 16 08 00 00 d1 07 00 00 8e 07 00 00 4d 07 00 00 0f 07 00 00 d3 06 00 00 99 06 00 00 62 06 00 00 fb 05 00 00 9c 05 00 00 46 05 00 00 f8 04 00 00 b0 04 00 00 70 04 00 00 35 04 00 00 00 04 00 00 a4 03 00 00 57 03 00 00 e4 02 00 00 94 02 00 00 5b 02 00 00 31 02 00 00 12 02 00 00 fb 01 00 00 e9 01 00 00 dc 01 00 00 d1 01 00 00 c8 01 00 00 c1 01 00 00 bb 01 00 00 b7 01 00 00 b3 01 00 00 b0 01 00 00 ad 01 00 00 ab 01 00 00 a9 01 00 00 a7 01 00 00 a6 01 00 00 a4 01 00 00 a3 01 00 00 a2 01 00 00 20 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00 40 00 00 00 00 00 00 00 ff 00 00 00]; }; iq_shdr { size = [ec 01 00 00];